Merge "CEC: Stub MHL Controller" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 419b1ed..35d13d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -204,6 +204,7 @@
core/java/android/os/IUserManager.aidl \
core/java/android/os/IVibratorService.aidl \
core/java/android/service/notification/INotificationListener.aidl \
+ core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
core/java/android/service/notification/IConditionListener.aidl \
core/java/android/service/notification/IConditionProvider.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
@@ -489,8 +490,11 @@
frameworks/base/location/java/android/location/FusedBatchOptions.aidl \
frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \
frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
+ frameworks/base/media/java/android/media/AudioAttributes.aidl \
+ frameworks/base/media/java/android/media/MediaDescription.aidl \
frameworks/base/media/java/android/media/MediaMetadata.aidl \
frameworks/base/media/java/android/media/Rating.aidl \
+ frameworks/base/media/java/android/media/browse/MediaBrowser.aidl \
frameworks/base/media/java/android/media/session/MediaSession.aidl \
frameworks/base/media/java/android/media/session/PlaybackState.aidl \
frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
diff --git a/api/current.txt b/api/current.txt
index a0d47e4..ba8551a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -260,6 +260,7 @@
public static final class R.attr {
ctor public R.attr();
+ field public static final int __removed2 = 16843937; // 0x10104a1
field public static final int absListViewStyle = 16842858; // 0x101006a
field public static final int accessibilityEventTypes = 16843648; // 0x1010380
field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
@@ -482,7 +483,7 @@
field public static final int datePickerMode = 16843956; // 0x10104b4
field public static final int datePickerStyle = 16843612; // 0x101035c
field public static final int dateTextAppearance = 16843593; // 0x1010349
- field public static final int dayOfWeekBackgroundColor = 16843924; // 0x1010494
+ field public static final int dayOfWeekBackground = 16843924; // 0x1010494
field public static final int dayOfWeekTextAppearance = 16843925; // 0x1010495
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -663,7 +664,6 @@
field public static final int hasCode = 16842764; // 0x101000c
field public static final int headerAmPmTextAppearance = 16843936; // 0x10104a0
field public static final int headerBackground = 16843055; // 0x101012f
- field public static final int headerBackgroundColor = 16843937; // 0x10104a1
field public static final int headerDayOfMonthTextAppearance = 16843927; // 0x1010497
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int headerMonthTextAppearance = 16843926; // 0x1010496
@@ -968,6 +968,7 @@
field public static final int pathData = 16843807; // 0x101041f
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
+ field public static final int patternPathData = 16843979; // 0x10104cb
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
field public static final int permissionGroup = 16842762; // 0x101000a
@@ -1061,6 +1062,7 @@
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
field public static final int restrictionType = 16843923; // 0x1010493
+ field public static final int resumeWhilePausing = 16843955; // 0x10104b3
field public static final int reversible = 16843851; // 0x101044b
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
@@ -3455,7 +3457,7 @@
method public boolean navigateUpToFromChild(android.app.Activity, android.content.Intent);
method public void onActionModeFinished(android.view.ActionMode);
method public void onActionModeStarted(android.view.ActionMode);
- method protected void onActivityReenter(int, android.content.Intent);
+ method public void onActivityReenter(int, android.content.Intent);
method protected void onActivityResult(int, int, android.content.Intent);
method public void onAttachFragment(android.app.Fragment);
method public void onAttachedToWindow();
@@ -3466,7 +3468,7 @@
method public boolean onContextItemSelected(android.view.MenuItem);
method public void onContextMenuClosed(android.view.Menu);
method protected void onCreate(android.os.Bundle);
- method protected void onCreate(android.os.Bundle, android.os.PersistableBundle);
+ method public void onCreate(android.os.Bundle, android.os.PersistableBundle);
method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
method public java.lang.CharSequence onCreateDescription();
method protected deprecated android.app.Dialog onCreateDialog(int);
@@ -3498,7 +3500,7 @@
method public void onPanelClosed(int, android.view.Menu);
method protected void onPause();
method protected void onPostCreate(android.os.Bundle);
- method protected void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
+ method public void onPostCreate(android.os.Bundle, android.os.PersistableBundle);
method protected void onPostResume();
method protected deprecated void onPrepareDialog(int, android.app.Dialog);
method protected deprecated void onPrepareDialog(int, android.app.Dialog, android.os.Bundle);
@@ -3508,11 +3510,11 @@
method public void onProvideAssistData(android.os.Bundle);
method protected void onRestart();
method protected void onRestoreInstanceState(android.os.Bundle);
- method protected void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
+ method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle);
method protected void onResume();
method public deprecated java.lang.Object onRetainNonConfigurationInstance();
method protected void onSaveInstanceState(android.os.Bundle);
- method protected void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
+ method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle);
method public boolean onSearchRequested();
method protected void onStart();
method protected void onStop();
@@ -3544,8 +3546,8 @@
method public void setContentView(android.view.View);
method public void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public final void setDefaultKeyMode(int);
- method public void setEnterSharedElementListener(android.app.SharedElementListener);
- method public void setExitSharedElementListener(android.app.SharedElementListener);
+ method public void setEnterSharedElementCallback(android.app.SharedElementCallback);
+ method public void setExitSharedElementCallback(android.app.SharedElementCallback);
method public final void setFeatureDrawable(int, android.graphics.drawable.Drawable);
method public final void setFeatureDrawableAlpha(int, int);
method public final void setFeatureDrawableResource(int, int);
@@ -3790,7 +3792,6 @@
public class ActivityOptions {
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
- method public static deprecated android.app.ActivityOptions makeLaunchTaskBehindAnimation();
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
@@ -4319,9 +4320,9 @@
method public void setAllowEnterTransitionOverlap(boolean);
method public void setAllowReturnTransitionOverlap(boolean);
method public void setArguments(android.os.Bundle);
- method public void setEnterSharedElementTransitionListener(android.app.SharedElementListener);
+ method public void setEnterSharedElementTransitionCallback(android.app.SharedElementCallback);
method public void setEnterTransition(android.transition.Transition);
- method public void setExitSharedElementTransitionListener(android.app.SharedElementListener);
+ method public void setExitSharedElementTransitionCallback(android.app.SharedElementCallback);
method public void setExitTransition(android.transition.Transition);
method public void setHasOptionsMenu(boolean);
method public void setInitialSavedState(android.app.Fragment.SavedState);
@@ -5192,14 +5193,14 @@
field public static final int START_STICKY_COMPATIBILITY = 0; // 0x0
}
- public abstract class SharedElementListener {
- ctor public SharedElementListener();
- method public android.os.Parcelable captureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
- method public android.view.View createSnapshotView(android.content.Context, android.os.Parcelable);
- method public void handleRejectedSharedElements(java.util.List<android.view.View>);
- method public void remapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>);
- method public void setSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
- method public void setSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+ public abstract class SharedElementCallback {
+ ctor public SharedElementCallback();
+ method public android.os.Parcelable onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix, android.graphics.RectF);
+ method public android.view.View onCreateSnapshotView(android.content.Context, android.os.Parcelable);
+ method public void onMapSharedElements(java.util.List<java.lang.String>, java.util.Map<java.lang.String, android.view.View>);
+ method public void onRejectSharedElements(java.util.List<android.view.View>);
+ method public void onSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+ method public void onSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
}
public deprecated class TabActivity extends android.app.ActivityGroup {
@@ -5391,8 +5392,8 @@
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED";
- field public static final java.lang.String ACTION_LOCK_TASK_ENTERING = "android.app.action.ACTION_LOCK_TASK_ENTERING";
- field public static final java.lang.String ACTION_LOCK_TASK_EXITING = "android.app.action.ACTION_LOCK_TASK_EXITING";
+ field public static final java.lang.String ACTION_LOCK_TASK_ENTERING = "android.app.action.LOCK_TASK_ENTERING";
+ field public static final java.lang.String ACTION_LOCK_TASK_EXITING = "android.app.action.LOCK_TASK_EXITING";
field public static final java.lang.String ACTION_PASSWORD_CHANGED = "android.app.action.ACTION_PASSWORD_CHANGED";
field public static final java.lang.String ACTION_PASSWORD_EXPIRING = "android.app.action.ACTION_PASSWORD_EXPIRING";
field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
@@ -5507,26 +5508,25 @@
field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0
field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
- field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.ADMIN_EXTRA_BUNDLE";
- field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+ field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
- field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
- field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
- field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
- field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.WIFI_HIDDEN";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.WIFI_PAC_URL";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.WIFI_PASSWORD";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.WIFI_PROXY_HOST";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.WIFI_PROXY_PORT";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.WIFI_SECURITY_TYPE";
- field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.WIFI_SSID";
- field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
- field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
+ field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
+ field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
+ field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_HIDDEN = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PAC_URL = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PASSWORD = "android.app.extra.PROVISIONING_WIFI_PASSWORD";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_HOST = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
+ field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
+ field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
+ field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
field public static final int KEYGUARD_DISABLE_FINGERPRINT = 32; // 0x20
@@ -5535,6 +5535,7 @@
field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10
field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8
field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
+ field public static final java.lang.String KEY_PROVISIONING_EMAIL_ADDRESS = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
field public static final java.lang.String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning";
field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
@@ -5706,6 +5707,19 @@
package android.app.usage {
+ public final class ConfigurationStats implements android.os.Parcelable {
+ ctor public ConfigurationStats(android.app.usage.ConfigurationStats);
+ method public int describeContents();
+ method public int getActivationCount();
+ method public android.content.res.Configuration getConfiguration();
+ method public long getFirstTimeStamp();
+ method public long getLastTimeActive();
+ method public long getLastTimeStamp();
+ method public long getTotalTimeActive();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
public final class UsageEvents implements android.os.Parcelable {
method public int describeContents();
method public boolean getNextEvent(android.app.usage.UsageEvents.Event);
@@ -5718,9 +5732,11 @@
public static final class UsageEvents.Event {
ctor public UsageEvents.Event();
method public java.lang.String getClassName();
+ method public android.content.res.Configuration getConfiguration();
method public int getEventType();
method public java.lang.String getPackageName();
method public long getTimeStamp();
+ field public static final int CONFIGURATION_CHANGE = 5; // 0x5
field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
field public static final int MOVE_TO_FOREGROUND = 1; // 0x1
field public static final int NONE = 0; // 0x0
@@ -5741,6 +5757,7 @@
public final class UsageStatsManager {
method public java.util.Map<java.lang.String, android.app.usage.UsageStats> queryAndAggregateUsageStats(long, long);
+ method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
method public android.app.usage.UsageEvents queryEvents(long, long);
method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
field public static final int INTERVAL_BEST = 4; // 0x4
@@ -5859,7 +5876,7 @@
field public static final int RESIZE_VERTICAL = 2; // 0x2
field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
- field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4
+ field public static final int WIDGET_CATEGORY_SEARCHBOX = 4; // 0x4
field public int autoAdvanceViewId;
field public android.content.ComponentName configure;
field public int icon;
@@ -7821,6 +7838,7 @@
field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
+ field public static final java.lang.String EXTRA_ASSIST_INPUT_HINT_KEYBOARD = "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
@@ -7867,7 +7885,7 @@
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
field public static final java.lang.String EXTRA_UID = "android.intent.extra.UID";
- field public static final java.lang.String EXTRA_USER = "android.intent.extra.user";
+ field public static final java.lang.String EXTRA_USER = "android.intent.extra.USER";
field public static final int FILL_IN_ACTION = 1; // 0x1
field public static final int FILL_IN_CATEGORIES = 4; // 0x4
field public static final int FILL_IN_CLIP_DATA = 128; // 0x80
@@ -8150,8 +8168,8 @@
}
public class RestrictionsManager {
+ method public android.content.Intent createLocalApprovalIntent();
method public android.os.Bundle getApplicationRestrictions();
- method public android.content.Intent getLocalApprovalIntent();
method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
method public boolean hasRestrictionsProvider();
method public void notifyPermissionResponse(java.lang.String, android.os.PersistableBundle);
@@ -8393,6 +8411,7 @@
field public static final int FLAG_MULTIPROCESS = 1; // 0x1
field public static final int FLAG_NO_HISTORY = 128; // 0x80
field public static final int FLAG_RELINQUISH_TASK_IDENTITY = 4096; // 0x1000
+ field public static final int FLAG_RESUME_WHILE_PAUSING = 16384; // 0x4000
field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10
field public static final int LAUNCH_MULTIPLE = 0; // 0x0
@@ -8597,21 +8616,16 @@
public class LauncherApps {
method public void addCallback(android.content.pm.LauncherApps.Callback);
- method public void addCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
- method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
- method public void addOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback, android.os.Handler);
method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(java.lang.String, android.os.UserHandle);
method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle);
- method public boolean isActivityEnabledForProfile(android.content.ComponentName, android.os.UserHandle);
method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle);
- method public boolean isPackageEnabledForProfile(java.lang.String, android.os.UserHandle);
+ method public void registerCallback(android.content.pm.LauncherApps.Callback);
+ method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
method public void removeCallback(android.content.pm.LauncherApps.Callback);
- method public void removeOnAppsChangedCallback(android.content.pm.LauncherApps.OnAppsChangedCallback);
method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
- method public void showAppDetailsForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
- method public void startActivityForProfile(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
+ method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
}
public static abstract class LauncherApps.Callback {
@@ -8623,10 +8637,6 @@
method public abstract void onPackagesUnavailable(java.lang.String[], android.os.UserHandle, boolean);
}
- public static abstract class LauncherApps.OnAppsChangedCallback extends android.content.pm.LauncherApps.Callback {
- ctor public LauncherApps.OnAppsChangedCallback();
- }
-
public class PackageInfo implements android.os.Parcelable {
ctor public PackageInfo();
method public int describeContents();
@@ -8664,15 +8674,17 @@
public class PackageInstaller {
method public void abandonSession(int);
- method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
- method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
method public int createSession(android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
- method public android.content.pm.PackageInstaller.Session openSession(int);
- method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
+ method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
method public void uninstall(java.lang.String, android.content.IntentSender);
+ method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public void updateSessionAppIcon(int, android.graphics.Bitmap);
+ method public void updateSessionAppLabel(int, java.lang.CharSequence);
field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
@@ -8699,15 +8711,15 @@
method public java.lang.String[] getNames() throws java.io.IOException;
method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
- method public void setProgress(float);
+ method public void setStagingProgress(float);
}
public static abstract class PackageInstaller.SessionCallback {
ctor public PackageInstaller.SessionCallback();
- method public abstract void onClosed(int);
+ method public abstract void onActiveChanged(int, boolean);
+ method public abstract void onBadgingChanged(int);
method public abstract void onCreated(int);
method public abstract void onFinished(int, boolean);
- method public abstract void onOpened(int);
method public abstract void onProgressChanged(int, float);
}
@@ -8720,7 +8732,7 @@
method public java.lang.String getInstallerPackageName();
method public float getProgress();
method public int getSessionId();
- method public boolean isOpen();
+ method public boolean isActive();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -8827,6 +8839,9 @@
method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public abstract java.lang.String[] getSystemSharedLibraryNames();
method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+ method public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+ method public abstract android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
+ method public abstract java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract boolean hasSystemFeature(java.lang.String);
method public abstract boolean isSafeMode();
@@ -8857,6 +8872,7 @@
field public static final java.lang.String EXTRA_VERIFICATION_RESULT = "android.content.pm.extra.VERIFICATION_RESULT";
field public static final java.lang.String FEATURE_APP_WIDGETS = "android.software.app_widgets";
field public static final java.lang.String FEATURE_AUDIO_LOW_LATENCY = "android.hardware.audio.low_latency";
+ field public static final java.lang.String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
field public static final java.lang.String FEATURE_BACKUP = "android.software.backup";
field public static final java.lang.String FEATURE_BLUETOOTH = "android.hardware.bluetooth";
field public static final java.lang.String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le";
@@ -8875,6 +8891,7 @@
field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
+ field public static final java.lang.String FEATURE_GAMEPAD = "android.hardware.gamepad";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
@@ -11419,8 +11436,6 @@
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
method public int getColor();
method public android.graphics.PorterDuff.Mode getMode();
- method public void setColor(int);
- method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -12651,27 +12666,27 @@
public abstract class CameraCaptureSession implements java.lang.AutoCloseable {
ctor public CameraCaptureSession();
method public abstract void abortCaptures() throws android.hardware.camera2.CameraAccessException;
- method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void close();
method public abstract android.hardware.camera2.CameraDevice getDevice();
- method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraCaptureSession.CaptureCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
}
- public static abstract class CameraCaptureSession.CaptureListener {
- ctor public CameraCaptureSession.CaptureListener();
+ public static abstract class CameraCaptureSession.CaptureCallback {
+ ctor public CameraCaptureSession.CaptureCallback();
method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
method public void onCaptureSequenceAborted(android.hardware.camera2.CameraCaptureSession, int);
method public void onCaptureSequenceCompleted(android.hardware.camera2.CameraCaptureSession, int, long);
- method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long);
+ method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long, long);
}
- public static abstract class CameraCaptureSession.StateListener {
- ctor public CameraCaptureSession.StateListener();
+ public static abstract class CameraCaptureSession.StateCallback {
+ ctor public CameraCaptureSession.StateCallback();
method public void onActive(android.hardware.camera2.CameraCaptureSession);
method public void onClosed(android.hardware.camera2.CameraCaptureSession);
method public abstract void onConfigureFailed(android.hardware.camera2.CameraCaptureSession);
@@ -12758,7 +12773,7 @@
public abstract class CameraDevice implements java.lang.AutoCloseable {
method public abstract void close();
method public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
- method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public abstract void createCaptureSession(java.util.List<android.view.Surface>, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract java.lang.String getId();
field public static final int TEMPLATE_MANUAL = 6; // 0x6
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
@@ -12768,8 +12783,8 @@
field public static final int TEMPLATE_ZERO_SHUTTER_LAG = 5; // 0x5
}
- public static abstract class CameraDevice.StateListener {
- ctor public CameraDevice.StateListener();
+ public static abstract class CameraDevice.StateCallback {
+ ctor public CameraDevice.StateCallback();
method public void onClosed(android.hardware.camera2.CameraDevice);
method public abstract void onDisconnected(android.hardware.camera2.CameraDevice);
method public abstract void onError(android.hardware.camera2.CameraDevice, int);
@@ -12782,15 +12797,15 @@
}
public final class CameraManager {
- method public void addAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener, android.os.Handler);
method public android.hardware.camera2.CameraCharacteristics getCameraCharacteristics(java.lang.String) throws android.hardware.camera2.CameraAccessException;
method public java.lang.String[] getCameraIdList() throws android.hardware.camera2.CameraAccessException;
- method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
- method public void removeAvailabilityListener(android.hardware.camera2.CameraManager.AvailabilityListener);
+ method public void openCamera(java.lang.String, android.hardware.camera2.CameraDevice.StateCallback, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+ method public void registerAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback, android.os.Handler);
+ method public void unregisterAvailabilityCallback(android.hardware.camera2.CameraManager.AvailabilityCallback);
}
- public static abstract class CameraManager.AvailabilityListener {
- ctor public CameraManager.AvailabilityListener();
+ public static abstract class CameraManager.AvailabilityCallback {
+ ctor public CameraManager.AvailabilityCallback();
method public void onCameraAvailable(java.lang.String);
method public void onCameraUnavailable(java.lang.String);
}
@@ -13999,7 +14014,7 @@
ctor public SettingInjectorService(java.lang.String);
method public final android.os.IBinder onBind(android.content.Intent);
method protected abstract boolean onGetEnabled();
- method protected deprecated java.lang.String onGetSummary();
+ method protected abstract deprecated java.lang.String onGetSummary();
method public final void onStart(android.content.Intent, int);
method public final int onStartCommand(android.content.Intent, int, int);
field public static final java.lang.String ACTION_INJECTED_SETTING_CHANGED = "android.location.InjectedSettingChanged";
@@ -14029,7 +14044,9 @@
field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4
field public static final int CONTENT_TYPE_SPEECH = 1; // 0x1
field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0
+ field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
+ field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
field public static final int USAGE_ALARM = 4; // 0x4
field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -14214,9 +14231,9 @@
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
- field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
- field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.encodings";
- field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+ field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
+ field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
+ field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
@@ -14655,6 +14672,7 @@
public static final class MediaCodec.CryptoException extends java.lang.RuntimeException {
ctor public MediaCodec.CryptoException(int, java.lang.String);
method public int getErrorCode();
+ field public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4; // 0x4
field public static final int ERROR_KEY_EXPIRED = 2; // 0x2
field public static final int ERROR_NO_KEY = 1; // 0x1
field public static final int ERROR_RESOURCE_BUSY = 3; // 0x3
@@ -14688,7 +14706,7 @@
public static final class MediaCodecInfo.CodecCapabilities {
ctor public MediaCodecInfo.CodecCapabilities();
- method public static android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
+ method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(java.lang.String, int, int);
method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
method public android.media.MediaFormat getDefaultFormat();
method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
@@ -15920,13 +15938,13 @@
}
public abstract class VolumeProvider {
- ctor public VolumeProvider(int, int);
+ ctor public VolumeProvider(int, int, int);
+ method public final int getCurrentVolume();
method public final int getMaxVolume();
method public final int getVolumeControl();
- method public final void notifyVolumeChanged();
method public void onAdjustVolume(int);
- method public abstract int onGetCurrentVolume();
method public void onSetVolumeTo(int);
+ method public final void setCurrentVolume(int);
field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
@@ -16259,7 +16277,7 @@
}
public static class MediaBrowser.MediaItem implements android.os.Parcelable {
- ctor public MediaBrowser.MediaItem(int, android.media.MediaDescription);
+ ctor public MediaBrowser.MediaItem(android.media.MediaDescription, int);
method public int describeContents();
method public android.media.MediaDescription getDescription();
method public int getFlags();
@@ -16360,8 +16378,6 @@
public final class MediaController {
ctor public MediaController(android.content.Context, android.media.session.MediaSession.Token);
- method public void addCallback(android.media.session.MediaController.Callback);
- method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
method public void adjustVolume(int, int);
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
method public android.os.Bundle getExtras();
@@ -16376,9 +16392,11 @@
method public android.app.PendingIntent getSessionActivity();
method public android.media.session.MediaSession.Token getSessionToken();
method public android.media.session.MediaController.TransportControls getTransportControls();
- method public void removeCallback(android.media.session.MediaController.Callback);
+ method public void registerCallback(android.media.session.MediaController.Callback);
+ method public void registerCallback(android.media.session.MediaController.Callback, android.os.Handler);
method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
method public void setVolumeTo(int, int);
+ method public void unregisterCallback(android.media.session.MediaController.Callback);
}
public static abstract class MediaController.Callback {
@@ -16704,10 +16722,10 @@
}
public final class TvInputInfo implements android.os.Parcelable {
+ method public android.content.Intent createSettingsIntent();
+ method public android.content.Intent createSetupIntent();
method public int describeContents();
method public java.lang.String getId();
- method public android.content.Intent getIntentForSettingsActivity();
- method public android.content.Intent getIntentForSetupActivity();
method public java.lang.String getParentId();
method public android.content.pm.ServiceInfo getServiceInfo();
method public int getType();
@@ -16715,7 +16733,8 @@
method public android.graphics.drawable.Drawable loadIcon(android.content.Context);
method public java.lang.CharSequence loadLabel(android.content.Context);
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String EXTRA_INPUT_ID = "inputId";
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final java.lang.String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
field public static final int TYPE_COMPONENT = 1004; // 0x3ec
field public static final int TYPE_COMPOSITE = 1001; // 0x3e9
field public static final int TYPE_DISPLAY_PORT = 1008; // 0x3f0
@@ -16734,23 +16753,23 @@
method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
method public boolean isParentalControlsEnabled();
method public boolean isRatingBlocked(android.media.tv.TvContentRating);
- method public void registerListener(android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
- method public void unregisterListener(android.media.tv.TvInputManager.TvInputListener);
- field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
- field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
- field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
+ method public void registerCallback(android.media.tv.TvInputManager.TvInputCallback, android.os.Handler);
+ method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
+ field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+ field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
+ field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
- field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
+ field public static final java.lang.String META_DATA_CONTENT_RATING_SYSTEMS = "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
field public static final int VIDEO_UNAVAILABLE_REASON_TUNING = 1; // 0x1
field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2
}
- public static abstract class TvInputManager.TvInputListener {
- ctor public TvInputManager.TvInputListener();
+ public static abstract class TvInputManager.TvInputCallback {
+ ctor public TvInputManager.TvInputCallback();
method public void onInputAdded(java.lang.String);
method public void onInputRemoved(java.lang.String);
method public void onInputStateChanged(java.lang.String, int);
@@ -16841,10 +16860,10 @@
method public boolean onUnhandledInputEvent(android.view.InputEvent);
method public void reset();
method public void selectTrack(int, java.lang.String);
+ method public void setCallback(android.media.tv.TvView.TvInputCallback);
method public void setCaptionEnabled(boolean);
method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
method public void setStreamVolume(float);
- method public void setTvInputListener(android.media.tv.TvView.TvInputListener);
method public void tune(java.lang.String, android.net.Uri);
}
@@ -16852,8 +16871,8 @@
method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
}
- public static abstract class TvView.TvInputListener {
- ctor public TvView.TvInputListener();
+ public static abstract class TvView.TvInputCallback {
+ ctor public TvView.TvInputCallback();
method public void onChannelRetuned(java.lang.String, android.net.Uri);
method public void onConnectionFailed(java.lang.String);
method public void onContentAllowed(java.lang.String);
@@ -16998,6 +17017,7 @@
package android.net {
public class ConnectivityManager {
+ method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public android.net.NetworkInfo getActiveNetworkInfo();
method public android.net.NetworkInfo[] getAllNetworkInfo();
method public android.net.Network[] getAllNetworks();
@@ -17011,8 +17031,8 @@
method public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method public static boolean isNetworkTypeValid(int);
- method public void registerDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+ method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public void reportBadNetwork(android.net.Network);
method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
method public deprecated boolean requestRouteToHost(int, int);
@@ -17020,7 +17040,6 @@
method public static boolean setProcessDefaultNetwork(android.net.Network);
method public deprecated int startUsingNetworkFeature(int, java.lang.String);
method public deprecated int stopUsingNetworkFeature(int, java.lang.String);
- method public void unregisterDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
@@ -17094,6 +17113,7 @@
method public int getPrefixLength();
method public int getScope();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public final class LinkProperties implements android.os.Parcelable {
@@ -17306,6 +17326,7 @@
method public android.net.Uri getPacFileUrl();
method public int getPort();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public abstract class PskKeyManager {
@@ -21546,7 +21567,7 @@
field public static final int JELLY_BEAN_MR2 = 18; // 0x12
field public static final int KITKAT = 19; // 0x13
field public static final int KITKAT_WATCH = 20; // 0x14
- field public static final int L = 10000; // 0x2710
+ field public static final int L = 21; // 0x15
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -21584,6 +21605,8 @@
method public short getShort(java.lang.String);
method public short getShort(java.lang.String, short);
method public short[] getShortArray(java.lang.String);
+ method public android.util.Size getSize(java.lang.String);
+ method public android.util.SizeF getSizeF(java.lang.String);
method public android.util.SparseArray<T> getSparseParcelableArray(java.lang.String);
method public java.util.ArrayList<java.lang.String> getStringArrayList(java.lang.String);
method public boolean hasFileDescriptors();
@@ -21608,6 +21631,8 @@
method public void putSerializable(java.lang.String, java.io.Serializable);
method public void putShort(java.lang.String, short);
method public void putShortArray(java.lang.String, short[]);
+ method public void putSize(java.lang.String, android.util.Size);
+ method public void putSizeF(java.lang.String, android.util.SizeF);
method public void putSparseParcelableArray(java.lang.String, android.util.SparseArray<? extends android.os.Parcelable>);
method public void putStringArrayList(java.lang.String, java.util.ArrayList<java.lang.String>);
method public void readFromParcel(android.os.Parcel);
@@ -22059,6 +22084,8 @@
method public final android.os.PersistableBundle readPersistableBundle();
method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
method public final java.io.Serializable readSerializable();
+ method public final android.util.Size readSize();
+ method public final android.util.SizeF readSizeF();
method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
method public final android.util.SparseBooleanArray readSparseBooleanArray();
method public final java.lang.String readString();
@@ -22100,6 +22127,8 @@
method public final void writeParcelableArray(T[], int);
method public final void writePersistableBundle(android.os.PersistableBundle);
method public final void writeSerializable(java.io.Serializable);
+ method public final void writeSize(android.util.Size);
+ method public final void writeSizeF(android.util.SizeF);
method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
method public final void writeString(java.lang.String);
@@ -22439,9 +22468,6 @@
public class UserManager {
method public android.os.Bundle getApplicationRestrictions(java.lang.String);
- method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
- method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
- method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
method public long getSerialNumberForUser(android.os.UserHandle);
method public int getUserCount();
method public android.os.UserHandle getUserForSerialNumber(long);
@@ -22475,6 +22501,7 @@
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
+ field public static final java.lang.String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
field public static final java.lang.String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
field public static final java.lang.String DISALLOW_REMOVE_USER = "no_remove_user";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
@@ -23669,9 +23696,8 @@
field public static final java.lang.String DATE = "date";
field public static final java.lang.String DEFAULT_SORT_ORDER = "date DESC";
field public static final java.lang.String DURATION = "duration";
- field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.call_type_filter";
+ field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER";
field public static final java.lang.String FEATURES = "features";
- field public static final int FEATURES_NONE = 0; // 0x0
field public static final int FEATURES_VIDEO = 1; // 0x1
field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
field public static final int INCOMING_TYPE = 1; // 0x1
@@ -24033,11 +24059,11 @@
public static final class ContactsContract.CommonDataKinds.Callable implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
ctor public ContactsContract.CommonDataKinds.Callable();
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
}
protected static abstract interface ContactsContract.CommonDataKinds.CommonColumns implements android.provider.ContactsContract.CommonDataKinds.BaseTypes {
@@ -24048,11 +24074,11 @@
public static final class ContactsContract.CommonDataKinds.Contactables implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
ctor public ContactsContract.CommonDataKinds.Contactables();
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
}
@@ -24060,15 +24086,15 @@
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
field public static final java.lang.String ADDRESS = "data1";
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/email_v2";
field public static final android.net.Uri CONTENT_LOOKUP_URI;
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/email_v2";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String DISPLAY_NAME = "data4";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final int TYPE_HOME = 1; // 0x1
field public static final int TYPE_MOBILE = 4; // 0x4
field public static final int TYPE_OTHER = 3; // 0x3
@@ -24078,10 +24104,10 @@
public static final class ContactsContract.CommonDataKinds.Event implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static int getTypeResource(java.lang.Integer);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_event";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String START_DATE = "data1";
field public static final int TYPE_ANNIVERSARY = 1; // 0x1
field public static final int TYPE_BIRTHDAY = 3; // 0x3
@@ -24089,19 +24115,19 @@
}
public static final class ContactsContract.CommonDataKinds.GroupMembership implements android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/group_membership";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String GROUP_ROW_ID = "data1";
field public static final java.lang.String GROUP_SOURCE_ID = "group_sourceid";
}
public static final class ContactsContract.CommonDataKinds.Identity implements android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/identity";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String IDENTITY = "data1";
field public static final java.lang.String NAMESPACE = "data2";
}
@@ -24111,11 +24137,11 @@
method public static final int getProtocolLabelResource(int);
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/im";
field public static final java.lang.String CUSTOM_PROTOCOL = "data6";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String PROTOCOL = "data5";
field public static final int PROTOCOL_AIM = 0; // 0x0
field public static final int PROTOCOL_CUSTOM = -1; // 0xffffffff
@@ -24133,10 +24159,10 @@
}
public static final class ContactsContract.CommonDataKinds.Nickname implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/nickname";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String NAME = "data1";
field public static final int TYPE_DEFAULT = 1; // 0x1
field public static final int TYPE_INITIALS = 5; // 0x5
@@ -24147,22 +24173,22 @@
}
public static final class ContactsContract.CommonDataKinds.Note implements android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/note";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String NOTE = "data1";
}
public static final class ContactsContract.CommonDataKinds.Organization implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String COMPANY = "data1";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/organization";
field public static final java.lang.String DEPARTMENT = "data5";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String JOB_DESCRIPTION = "data6";
field public static final java.lang.String OFFICE_LOCATION = "data9";
field public static final java.lang.String PHONETIC_NAME = "data8";
@@ -24175,13 +24201,13 @@
public static final class ContactsContract.CommonDataKinds.Phone implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String NORMALIZED_NUMBER = "data4";
field public static final java.lang.String NUMBER = "data1";
field public static final java.lang.String SEARCH_DISPLAY_NAME_KEY = "search_display_name";
@@ -24209,10 +24235,10 @@
}
public static final class ContactsContract.CommonDataKinds.Photo implements android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/photo";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String PHOTO = "data15";
field public static final java.lang.String PHOTO_FILE_ID = "data14";
}
@@ -24220,10 +24246,10 @@
public static final class ContactsContract.CommonDataKinds.Relation implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/relation";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String NAME = "data1";
field public static final int TYPE_ASSISTANT = 1; // 0x1
field public static final int TYPE_BROTHER = 2; // 0x2
@@ -24244,10 +24270,10 @@
public static final class ContactsContract.CommonDataKinds.SipAddress implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/sip_address";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String SIP_ADDRESS = "data1";
field public static final int TYPE_HOME = 1; // 0x1
field public static final int TYPE_OTHER = 3; // 0x3
@@ -24255,11 +24281,11 @@
}
public static final class ContactsContract.CommonDataKinds.StructuredName implements android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/name";
field public static final java.lang.String DISPLAY_NAME = "data1";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String FAMILY_NAME = "data3";
field public static final java.lang.String FULL_NAME_STYLE = "data10";
field public static final java.lang.String GIVEN_NAME = "data2";
@@ -24274,14 +24300,14 @@
public static final class ContactsContract.CommonDataKinds.StructuredPostal implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
method public static final java.lang.CharSequence getTypeLabel(android.content.res.Resources, int, java.lang.CharSequence);
method public static final int getTypeLabelResource(int);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CITY = "data7";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/postal-address_v2";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/postal-address_v2";
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String COUNTRY = "data10";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String FORMATTED_ADDRESS = "data1";
field public static final java.lang.String NEIGHBORHOOD = "data6";
field public static final java.lang.String POBOX = "data5";
@@ -24294,10 +24320,10 @@
}
public static final class ContactsContract.CommonDataKinds.Website implements android.provider.ContactsContract.CommonDataKinds.CommonColumns android.provider.ContactsContract.DataColumnsWithJoins {
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/website";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final int TYPE_BLOG = 2; // 0x2
field public static final int TYPE_FTP = 6; // 0x6
field public static final int TYPE_HOME = 4; // 0x4
@@ -24345,7 +24371,6 @@
method public static deprecated void markAsContacted(android.content.ContentResolver, long);
method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri, boolean);
method public static java.io.InputStream openContactPhotoInputStream(android.content.ContentResolver, android.net.Uri);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final android.net.Uri CONTENT_FILTER_URI;
field public static final android.net.Uri CONTENT_FREQUENT_URI;
field public static final android.net.Uri CONTENT_GROUP_URI;
@@ -24358,8 +24383,9 @@
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String CONTENT_VCARD_TYPE = "text/x-vcard";
field public static final android.net.Uri CONTENT_VCARD_URI;
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
}
public static final class ContactsContract.Contacts.AggregationSuggestions implements android.provider.BaseColumns android.provider.ContactsContract.ContactOptionsColumns android.provider.ContactsContract.ContactStatusColumns android.provider.ContactsContract.ContactsColumns {
@@ -24404,11 +24430,11 @@
public static final class ContactsContract.Data implements android.provider.ContactsContract.DataColumnsWithJoins {
method public static android.net.Uri getContactLookupUri(android.content.ContentResolver, android.net.Uri);
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/data";
field public static final android.net.Uri CONTENT_URI;
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX = "android.provider.extra.ADDRESS_BOOK_INDEX";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
+ field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
field public static final java.lang.String VISIBLE_CONTACTS_ONLY = "visible_contacts_only";
}
@@ -24652,7 +24678,7 @@
ctor public ContactsContract.QuickContact();
method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
- field public static final java.lang.String ACTION_QUICK_CONTACT = "com.android.contacts.action.QUICK_CONTACT";
+ field public static final java.lang.String ACTION_QUICK_CONTACT = "android.provider.action.QUICK_CONTACT";
field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "android.provider.extra.EXCLUDE_MIMES";
field public static final int MODE_LARGE = 3; // 0x3
field public static final int MODE_MEDIUM = 2; // 0x2
@@ -27039,7 +27065,7 @@
method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
method public void setSessionToken(android.media.session.MediaSession.Token);
- field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+ field public static final java.lang.String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
}
public static final class MediaBrowserService.BrowserRoot {
@@ -27160,9 +27186,9 @@
package android.service.voice {
public class AlwaysOnHotwordDetector {
- method public android.content.Intent createIntentToEnroll();
- method public android.content.Intent createIntentToReEnroll();
- method public android.content.Intent createIntentToUnEnroll();
+ method public android.content.Intent createEnrollIntent();
+ method public android.content.Intent createReEnrollIntent();
+ method public android.content.Intent createUnEnrollIntent();
method public int getSupportedRecognitionModes();
method public boolean startRecognition(int);
method public boolean stopRecognition();
@@ -27242,6 +27268,7 @@
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
+ method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
method public void onCreate(android.view.SurfaceHolder);
method public void onDesiredSizeChanged(int, int);
@@ -27395,11 +27422,12 @@
ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener);
ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String);
method public int addEarcon(java.lang.String, java.lang.String, int);
- method public int addEarcon(java.lang.String, java.lang.String);
+ method public deprecated int addEarcon(java.lang.String, java.lang.String);
+ method public int addEarcon(java.lang.String, java.io.File);
method public int addSpeech(java.lang.String, java.lang.String, int);
method public int addSpeech(java.lang.CharSequence, java.lang.String, int);
method public int addSpeech(java.lang.String, java.lang.String);
- method public int addSpeech(java.lang.CharSequence, java.lang.String);
+ method public int addSpeech(java.lang.CharSequence, java.io.File);
method public deprecated boolean areDefaultsEnforced();
method public java.util.Set<java.util.Locale> getAvailableLanguages();
method public java.lang.String getDefaultEngine();
@@ -27413,7 +27441,7 @@
method public java.util.Set<android.speech.tts.Voice> getVoices();
method public int isLanguageAvailable(java.util.Locale);
method public boolean isSpeaking();
- method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+ method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String);
method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
@@ -27426,10 +27454,10 @@
method public int setSpeechRate(float);
method public int setVoice(android.speech.tts.Voice);
method public void shutdown();
- method public int speak(java.lang.CharSequence, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+ method public int speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String);
method public deprecated int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
method public int stop();
- method public int synthesizeToFile(java.lang.CharSequence, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String, java.lang.String);
+ method public int synthesizeToFile(java.lang.CharSequence, android.os.Bundle, java.io.File, java.lang.String);
method public deprecated int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED";
field public static final int ERROR = -1; // 0xffffffff
@@ -27502,15 +27530,15 @@
public abstract class TextToSpeechService extends android.app.Service {
ctor public TextToSpeechService();
- method protected int isValidVoiceName(java.lang.String);
method public android.os.IBinder onBind(android.content.Intent);
method protected java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String);
method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
method protected abstract java.lang.String[] onGetLanguage();
- method protected java.util.List<android.speech.tts.Voice> onGetVoices();
+ method public java.util.List<android.speech.tts.Voice> onGetVoices();
method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String);
+ method public int onIsValidVoiceName(java.lang.String);
method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String);
- method protected int onLoadVoice(java.lang.String);
+ method public int onLoadVoice(java.lang.String);
method protected abstract void onStop();
method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback);
}
@@ -27531,7 +27559,7 @@
method public java.util.Locale getLocale();
method public java.lang.String getName();
method public int getQuality();
- method public boolean getRequiresNetworkConnection();
+ method public boolean isNetworkConnectionRequired();
method public void writeToParcel(android.os.Parcel, int);
field public static final int LATENCY_HIGH = 400; // 0x190
field public static final int LATENCY_LOW = 200; // 0xc8
@@ -28188,7 +28216,6 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int ROUTE_ALL = 15; // 0xf
field public static final int ROUTE_BLUETOOTH = 2; // 0x2
field public static final int ROUTE_EARPIECE = 1; // 0x1
field public static final int ROUTE_SPEAKER = 8; // 0x8
@@ -28201,17 +28228,19 @@
public abstract class Conference {
ctor public Conference(android.telecomm.PhoneAccountHandle);
- method public boolean addConnection(android.telecomm.Connection);
- method public void destroy();
+ method public final boolean addConnection(android.telecomm.Connection);
+ method public final void destroy();
method public final int getCapabilities();
method public final java.util.List<android.telecomm.Connection> getConnections();
- method public final android.telecomm.PhoneAccountHandle getPhoneAccount();
+ method public final android.telecomm.PhoneAccountHandle getPhoneAccountHandle();
method public final int getState();
method public void onDisconnect();
method public void onHold();
+ method public void onMerge();
method public void onSeparate(android.telecomm.Connection);
+ method public void onSwap();
method public void onUnhold();
- method public void removeConnection(android.telecomm.Connection);
+ method public final void removeConnection(android.telecomm.Connection);
method public final void setActive();
method public final void setCapabilities(int);
method public final void setDisconnected(int, java.lang.String);
@@ -28278,12 +28307,11 @@
}
public final class ConnectionRequest implements android.os.Parcelable {
- ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, int, android.os.Bundle);
+ ctor public ConnectionRequest(android.telecomm.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
method public int describeContents();
method public android.telecomm.PhoneAccountHandle getAccountHandle();
+ method public android.net.Uri getAddress();
method public android.os.Bundle getExtras();
- method public android.net.Uri getHandle();
- method public int getHandlePresentation();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -28314,16 +28342,16 @@
}
public class PhoneAccount implements android.os.Parcelable {
- method public static android.telecomm.PhoneAccount.Builder builder();
+ method public static android.telecomm.PhoneAccount.Builder builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
method public int describeContents();
method public android.telecomm.PhoneAccountHandle getAccountHandle();
+ method public android.net.Uri getAddress();
method public int getCapabilities();
- method public android.net.Uri getHandle();
method public android.graphics.drawable.Drawable getIcon(android.content.Context);
method public int getIconResId();
method public java.lang.CharSequence getLabel();
method public java.lang.CharSequence getShortDescription();
- method public java.lang.String getSubscriptionNumber();
+ method public android.net.Uri getSubscriptionAddress();
method public java.util.List<java.lang.String> getSupportedUriSchemes();
method public boolean supportsUriScheme(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
@@ -28336,17 +28364,14 @@
}
public static class PhoneAccount.Builder {
- ctor public PhoneAccount.Builder();
+ ctor public PhoneAccount.Builder(android.telecomm.PhoneAccountHandle, java.lang.CharSequence);
method public android.telecomm.PhoneAccount build();
- method public android.telecomm.PhoneAccount.Builder withAccountHandle(android.telecomm.PhoneAccountHandle);
- method public android.telecomm.PhoneAccount.Builder withCapabilities(int);
- method public android.telecomm.PhoneAccount.Builder withHandle(android.net.Uri);
- method public android.telecomm.PhoneAccount.Builder withIconResId(int);
- method public android.telecomm.PhoneAccount.Builder withLabel(java.lang.CharSequence);
- method public android.telecomm.PhoneAccount.Builder withShortDescription(java.lang.CharSequence);
- method public android.telecomm.PhoneAccount.Builder withSubscriptionNumber(java.lang.String);
- method public android.telecomm.PhoneAccount.Builder withSupportedUriScheme(java.lang.String);
- method public android.telecomm.PhoneAccount.Builder withSupportedUriSchemes(java.util.List<java.lang.String>);
+ method public android.telecomm.PhoneAccount.Builder setAddress(android.net.Uri);
+ method public android.telecomm.PhoneAccount.Builder setCapabilities(int);
+ method public android.telecomm.PhoneAccount.Builder setIconResId(int);
+ method public android.telecomm.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+ method public android.telecomm.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+ method public android.telecomm.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
}
public class PhoneAccountHandle implements android.os.Parcelable {
@@ -28362,13 +28387,13 @@
method public static java.lang.String toString(int);
field public static final int ADD_CALL = 16; // 0x10
field public static final int ALL = 255; // 0xff
- field public static final int GENERIC_CONFERENCE = 128; // 0x80
field public static final int HOLD = 1; // 0x1
- field public static final int MERGE_CALLS = 4; // 0x4
+ field public static final int MANAGE_CONFERENCE = 128; // 0x80
+ field public static final int MERGE_CONFERENCE = 4; // 0x4
field public static final int MUTE = 64; // 0x40
field public static final int RESPOND_VIA_TEXT = 32; // 0x20
field public static final int SUPPORT_HOLD = 2; // 0x2
- field public static final int SWAP_CALLS = 8; // 0x8
+ field public static final int SWAP_CONFERENCE = 8; // 0x8
}
public class PropertyPresentation {
@@ -28380,7 +28405,7 @@
}
public final class RemoteConference {
- method public final void addListener(android.telecomm.RemoteConference.Listener);
+ method public final void addCallback(android.telecomm.RemoteConference.Callback);
method public void disconnect();
method public final int getCallCapabilities();
method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
@@ -28388,13 +28413,13 @@
method public java.lang.String getDisconnectMessage();
method public final int getState();
method public void hold();
- method public final void removeListener(android.telecomm.RemoteConference.Listener);
+ method public final void removeCallback(android.telecomm.RemoteConference.Callback);
method public void separate(android.telecomm.RemoteConnection);
method public void unhold();
}
- public static abstract class RemoteConference.Listener {
- ctor public RemoteConference.Listener();
+ public static abstract class RemoteConference.Callback {
+ ctor public RemoteConference.Callback();
method public void onCapabilitiesChanged(android.telecomm.RemoteConference, int);
method public void onConnectionAdded(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
method public void onConnectionRemoved(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
@@ -28461,11 +28486,11 @@
public final class StatusHints implements android.os.Parcelable {
ctor public StatusHints(android.content.ComponentName, java.lang.CharSequence, int, android.os.Bundle);
method public int describeContents();
- method public android.content.ComponentName getComponentName();
method public android.os.Bundle getExtras();
method public android.graphics.drawable.Drawable getIcon(android.content.Context);
method public int getIconResId();
method public java.lang.CharSequence getLabel();
+ method public android.content.ComponentName getPackageName();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -28474,6 +28499,7 @@
method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
method public void cancelMissedCallsNotification();
method public void clearAccounts(java.lang.String);
+ method public android.telecomm.PhoneAccountHandle getConnectionManager();
method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount(java.lang.String);
method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
method public android.telecomm.PhoneAccount getPhoneAccount(android.telecomm.PhoneAccountHandle);
@@ -28484,16 +28510,17 @@
method public void registerPhoneAccount(android.telecomm.PhoneAccount);
method public void showInCallScreen(boolean);
method public void unregisterPhoneAccount(android.telecomm.PhoneAccountHandle);
- field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
- field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
+ field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
+ field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.action.SHOW_CALL_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecomm.extra.CALL_BACK_NUMBER";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecomm.extra.CALL_DISCONNECT_CAUSE";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
- field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.intent.extra.PHONE_ACCOUNT_HANDLE";
- field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
+ field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
}
}
@@ -28704,11 +28731,11 @@
method public int getStatus();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public static int INVALID_CHANNEL;
- field public static int STATUS_MISSING_RESOURCE;
- field public static int STATUS_NO_ERROR;
- field public static int STATUS_NO_SUCH_ELEMENT;
- field public static int STATUS_UNKNOWN_ERROR;
+ field public static final int INVALID_CHANNEL = -1; // 0xffffffff
+ field public static final int STATUS_MISSING_RESOURCE = 2; // 0x2
+ field public static final int STATUS_NO_ERROR = 1; // 0x1
+ field public static final int STATUS_NO_SUCH_ELEMENT = 3; // 0x3
+ field public static final int STATUS_UNKNOWN_ERROR = 4; // 0x4
}
public class NeighboringCellInfo implements android.os.Parcelable {
@@ -28853,41 +28880,26 @@
}
public final class SmsManager {
- method public android.net.Uri addMultimediaMessageDraft(android.net.Uri);
- method public android.net.Uri addTextMessageDraft(java.lang.String, java.lang.String);
- method public boolean archiveStoredConversation(long, boolean);
- method public boolean deleteStoredConversation(long);
- method public boolean deleteStoredMessage(android.net.Uri);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
- method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
- method public boolean getAutoPersisting();
+ method public void downloadMultimediaMessage(java.lang.String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method public android.os.Bundle getCarrierConfigValues();
method public static android.telephony.SmsManager getDefault();
- method public static android.telephony.SmsManager getSmsManagerUsingSubId(long);
- method public long getSubId();
- method public android.net.Uri importMultimediaMessage(android.net.Uri, java.lang.String, long, boolean, boolean);
- method public android.net.Uri importTextMessage(java.lang.String, int, java.lang.String, long, boolean, boolean);
method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
- method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.content.ContentValues, android.app.PendingIntent);
+ method public void sendMultimediaMessage(android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
- method public void sendStoredMultimediaMessage(android.net.Uri, android.content.ContentValues, android.app.PendingIntent);
- method public void sendStoredMultipartTextMessage(android.net.Uri, java.lang.String, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
- method public void sendStoredTextMessage(android.net.Uri, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
- method public void setAutoPersisting(boolean);
method public void updateMmsDownloadStatus(int, byte[]);
method public void updateMmsSendStatus(int, boolean);
method public void updateSmsSendStatus(int, boolean);
- method public boolean updateStoredMessageStatus(android.net.Uri, android.content.ContentValues);
- field public static final java.lang.String MESSAGE_STATUS_READ = "read";
- field public static final java.lang.String MESSAGE_STATUS_SEEN = "seen";
+ field public static final java.lang.String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
field public static final java.lang.String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled";
field public static final java.lang.String MMS_CONFIG_ALIAS_MAX_CHARS = "aliasMaxChars";
field public static final java.lang.String MMS_CONFIG_ALIAS_MIN_CHARS = "aliasMinChars";
field public static final java.lang.String MMS_CONFIG_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
field public static final java.lang.String MMS_CONFIG_APPEND_TRANSACTION_ID = "enabledTransID";
field public static final java.lang.String MMS_CONFIG_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
+ field public static final java.lang.String MMS_CONFIG_GROUP_MMS_ENABLED = "enableGroupMms";
field public static final java.lang.String MMS_CONFIG_HTTP_PARAMS = "httpParams";
field public static final java.lang.String MMS_CONFIG_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
field public static final java.lang.String MMS_CONFIG_MAX_IMAGE_HEIGHT = "maxImageHeight";
@@ -28915,13 +28927,10 @@
field public static final int MMS_ERROR_IO_ERROR = 5; // 0x5
field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
- field public static final java.lang.String MMS_EXTRA_DATA = "data";
field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2
- field public static final int SMS_TYPE_INCOMING = 0; // 0x0
- field public static final int SMS_TYPE_OUTGOING = 1; // 0x1
field public static final int STATUS_ON_ICC_FREE = 0; // 0x0
field public static final int STATUS_ON_ICC_READ = 1; // 0x1
field public static final int STATUS_ON_ICC_SENT = 5; // 0x5
@@ -28988,10 +28997,7 @@
}
public class TelephonyManager {
- method public void enableSimplifiedNetworkSettings(boolean);
- method public void enableSimplifiedNetworkSettings(long, boolean);
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
- method public int getCalculatedPreferredNetworkType();
method public int getCallState();
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
@@ -29008,14 +29014,11 @@
method public java.lang.String getNetworkOperatorName();
method public int getNetworkType();
method public int getPhoneType();
- method public int getPreferredNetworkType();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
method public java.lang.String getSimSerialNumber();
method public int getSimState();
- method public boolean getSimplifiedNetworkSettingsEnabled();
- method public boolean getSimplifiedNetworkSettingsEnabled(long);
method public java.lang.String getSubscriberId();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
@@ -29030,11 +29033,10 @@
method public boolean isSmsCapable();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
- method public boolean setCdmaSubscription(int);
+ method public boolean setGlobalPreferredNetworkType();
method public void setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public void setLine1NumberForDisplay(long, java.lang.String, java.lang.String);
- method public boolean setOperatorBrandOverride(java.lang.String, java.lang.String);
- method public boolean setPreferredNetworkType(int);
+ method public boolean setOperatorBrandOverride(java.lang.String);
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -29729,6 +29731,9 @@
method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public java.lang.String[] getSystemSharedLibraryNames();
method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
+ method public android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+ method public android.graphics.drawable.Drawable getUserBadgedIcon(android.graphics.drawable.Drawable, android.os.UserHandle);
+ method public java.lang.CharSequence getUserBadgedLabel(java.lang.CharSequence, android.os.UserHandle);
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public boolean hasSystemFeature(java.lang.String);
method public boolean isSafeMode();
@@ -31492,13 +31497,13 @@
method public abstract android.graphics.Path getPath(float, float, float, float);
}
- public class PatternMotion extends android.transition.PathMotion {
- ctor public PatternMotion();
- ctor public PatternMotion(android.content.Context, android.util.AttributeSet);
- ctor public PatternMotion(android.graphics.Path);
+ public class PatternPathMotion extends android.transition.PathMotion {
+ ctor public PatternPathMotion();
+ ctor public PatternPathMotion(android.content.Context, android.util.AttributeSet);
+ ctor public PatternPathMotion(android.graphics.Path);
method public android.graphics.Path getPath(float, float, float, float);
- method public android.graphics.Path getPattern();
- method public void setPattern(android.graphics.Path);
+ method public android.graphics.Path getPatternPath();
+ method public void setPatternPath(android.graphics.Path);
}
public final class Scene {
@@ -32132,23 +32137,17 @@
field public static final android.util.Rational ZERO;
}
- public final class Size implements android.os.Parcelable {
+ public final class Size {
ctor public Size(int, int);
- method public int describeContents();
method public int getHeight();
method public int getWidth();
method public static android.util.Size parseSize(java.lang.String) throws java.lang.NumberFormatException;
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
}
- public final class SizeF implements android.os.Parcelable {
+ public final class SizeF {
ctor public SizeF(float, float);
- method public int describeContents();
method public float getHeight();
method public float getWidth();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
}
public class SparseArray implements java.lang.Cloneable {
@@ -32498,8 +32497,6 @@
method public final long getRefreshPeriodNano();
method public final long getStartTimeNano();
field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
- field protected long[] mFramesPresentedTimeNano;
- field protected long mRefreshPeriodNano;
}
public class GestureDetector {
@@ -34332,7 +34329,7 @@
}
public final class ViewAnimationUtils {
- method public static final android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
+ method public static android.animation.Animator createCircularReveal(android.view.View, int, int, float, float);
}
public class ViewConfiguration {
@@ -34980,12 +34977,18 @@
public final class WindowInsets {
ctor public WindowInsets(android.view.WindowInsets);
+ method public android.view.WindowInsets consumeStableInsets();
method public android.view.WindowInsets consumeSystemWindowInsets();
+ method public int getStableInsetBottom();
+ method public int getStableInsetLeft();
+ method public int getStableInsetRight();
+ method public int getStableInsetTop();
method public int getSystemWindowInsetBottom();
method public int getSystemWindowInsetLeft();
method public int getSystemWindowInsetRight();
method public int getSystemWindowInsetTop();
method public boolean hasInsets();
+ method public boolean hasStableInsets();
method public boolean hasSystemWindowInsets();
method public boolean isConsumed();
method public boolean isRound();
@@ -35890,8 +35893,8 @@
public final class CursorAnchorInfo implements android.os.Parcelable {
ctor public CursorAnchorInfo(android.os.Parcel);
method public int describeContents();
- method public android.graphics.RectF getCharacterRect(int);
- method public int getCharacterRectFlags(int);
+ method public android.graphics.RectF getCharacterBounds(int);
+ method public int getCharacterBoundsFlags(int);
method public java.lang.CharSequence getComposingText();
method public int getComposingTextStart();
method public float getInsertionMarkerBaseline();
@@ -35906,11 +35909,12 @@
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_HAS_INVISIBLE_REGION = 2; // 0x2
field public static final int FLAG_HAS_VISIBLE_REGION = 1; // 0x1
+ field public static final int FLAG_IS_RTL = 4; // 0x4
}
public static final class CursorAnchorInfo.Builder {
ctor public CursorAnchorInfo.Builder();
- method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterBounds(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo build();
method public void reset();
method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
@@ -36538,6 +36542,7 @@
method public abstract java.lang.String getMethod();
method public abstract java.util.Map<java.lang.String, java.lang.String> getRequestHeaders();
method public abstract android.net.Uri getUrl();
+ method public abstract boolean hasGesture();
method public abstract boolean hasUserGestureInsecure();
method public abstract boolean isForMainFrame();
}
@@ -36826,7 +36831,7 @@
method public void setWebViewClient(android.webkit.WebViewClient);
method public deprecated boolean showFindDialog(java.lang.String, boolean);
method public void stopLoading();
- method public boolean zoomBy(float);
+ method public void zoomBy(float);
method public boolean zoomIn();
method public boolean zoomOut();
field public static final java.lang.String SCHEME_GEO = "geo:0,0?q=";
@@ -37552,6 +37557,7 @@
method public android.widget.CalendarView getCalendarView();
method public boolean getCalendarViewShown();
method public int getDayOfMonth();
+ method public int getFirstDayOfWeek();
method public long getMaxDate();
method public long getMinDate();
method public int getMonth();
@@ -37559,6 +37565,7 @@
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
method public void setCalendarViewShown(boolean);
+ method public void setFirstDayOfWeek(int);
method public void setMaxDate(long);
method public void setMinDate(long);
method public void setSpinnersShown(boolean);
diff --git a/api/removed.txt b/api/removed.txt
index a910e78..3c16276 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -1,19 +1,3 @@
-package android {
-
- public static final class R.attr {
- field public static final int __removed1 = 16843955; // 0x10104b3
- }
-
-}
-
-package android.app {
-
- public class KeyguardManager {
- method public android.content.Intent getConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
- }
-
-}
-
package android.media {
public class AudioFormat {
@@ -30,6 +14,12 @@
method public void wakeUp(long);
}
+ public class UserManager {
+ method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle, android.graphics.Rect, int);
+ method public android.graphics.drawable.Drawable getBadgedIconForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
+ method public java.lang.CharSequence getBadgedLabelForUser(java.lang.CharSequence, android.os.UserHandle);
+ }
+
}
package android.service.notification {
@@ -55,6 +45,8 @@
}
public final class CursorAnchorInfo implements android.os.Parcelable {
+ method public android.graphics.RectF getCharacterRect(int);
+ method public int getCharacterRectFlags(int);
method public boolean isInsertionMarkerClipped();
field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
@@ -65,6 +57,7 @@
}
public static final class CursorAnchorInfo.Builder {
+ method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
}
@@ -80,11 +73,3 @@
}
-package com.android.internal {
-
- public static final class R.attr {
- field public static final int __removed1 = 16843955; // 0x10104b3
- }
-
-}
-
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 5f7a17d..27a03b6 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -54,6 +54,10 @@
int action, in Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, long threadId);
+ boolean computeClickPointInScreen(int accessibilityWindowId, long accessibilityNodeId,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback,
+ long threadId);
+
AccessibilityWindowInfo getWindow(int windowId);
List<AccessibilityWindowInfo> getWindows();
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 9156eeb..7c13dbe 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -504,6 +504,10 @@
mStarted = true;
mPaused = false;
+ for (Node node : mNodes) {
+ node.animation.setAllowRunningAsynchronously(false);
+ }
+
if (mDuration >= 0) {
// If the duration was set on this AnimatorSet, pass it along to all child animations
for (Node node : mNodes) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8ab344e..89a9692 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -788,8 +788,8 @@
final Handler mHandler = new Handler();
ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
- SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER;
- SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER;
+ SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
+ SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
/** Return the intent that started this activity. */
public Intent getIntent() {
@@ -955,7 +955,7 @@
* @see #onRestoreInstanceState
* @see #onPostCreate
*/
- protected void onCreate(@Nullable Bundle savedInstanceState,
+ public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}
@@ -1040,7 +1040,7 @@
* @see #onResume
* @see #onSaveInstanceState
*/
- protected void onRestoreInstanceState(Bundle savedInstanceState,
+ public void onRestoreInstanceState(Bundle savedInstanceState,
PersistableBundle persistentState) {
if (savedInstanceState != null) {
onRestoreInstanceState(savedInstanceState);
@@ -1130,7 +1130,7 @@
*
* @see #onCreate
*/
- protected void onPostCreate(@Nullable Bundle savedInstanceState,
+ public void onPostCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
onPostCreate(savedInstanceState);
}
@@ -1380,7 +1380,7 @@
* @see #onRestoreInstanceState(Bundle, PersistableBundle)
* @see #onPause
*/
- protected void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
+ public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
onSaveInstanceState(outState);
}
@@ -4769,7 +4769,7 @@
* @param data An Intent, which can return result data to the caller
* (various data can be attached to Intent "extras").
*/
- protected void onActivityReenter(int resultCode, Intent data) {
+ public void onActivityReenter(int resultCode, Intent data) {
}
/**
@@ -5410,6 +5410,7 @@
mTranslucentCallback = callback;
mChangeCanvasToTranslucent =
ActivityManagerNative.getDefault().convertToTranslucent(mToken, options);
+ WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);
drawComplete = true;
} catch (RemoteException e) {
// Make callback return as though it timed out.
@@ -5778,33 +5779,33 @@
/**
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
- * android.view.View, String)} was used to start an Activity, <var>listener</var>
+ * android.view.View, String)} was used to start an Activity, <var>callback</var>
* will be called to handle shared elements on the <i>launched</i> Activity. This requires
* {@link Window#FEATURE_CONTENT_TRANSITIONS}.
*
- * @param listener Used to manipulate shared element transitions on the launched Activity.
+ * @param callback Used to manipulate shared element transitions on the launched Activity.
*/
- public void setEnterSharedElementListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setEnterSharedElementCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mEnterTransitionListener = listener;
+ mEnterTransitionListener = callback;
}
/**
* When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
- * android.view.View, String)} was used to start an Activity, <var>listener</var>
+ * android.view.View, String)} was used to start an Activity, <var>callback</var>
* will be called to handle shared elements on the <i>launching</i> Activity. Most
* calls will only come when returning from the started Activity.
* This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
*
- * @param listener Used to manipulate shared element transitions on the launching Activity.
+ * @param callback Used to manipulate shared element transitions on the launching Activity.
*/
- public void setExitSharedElementListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setExitSharedElementCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mExitTransitionListener = listener;
+ mExitTransitionListener = callback;
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3e03893..9486a72 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2656,17 +2656,24 @@
/**
* Start an activity in this task. Brings the task to the foreground. If this task
- * is not currently active (that is, its id < 0), then the activity being started
- * needs to be started as a new task and the Intent's ComponentName must match the
- * base ComponenentName of the recent task entry. Otherwise, the activity being
- * started must <b>not</b> be launched as a new task -- not through explicit intent
- * flags nor implicitly as the singleTask or singleInstance launch modes.
+ * is not currently active (that is, its id < 0), then a new activity for the given
+ * Intent will be launched as the root of the task and the task brought to the
+ * foreground. Otherwise, if this task is currently active and the Intent does not specify
+ * an activity to launch in a new task, then a new activity for the given Intent will
+ * be launched on top of the task and the task brought to the foreground. If this
+ * task is currently active and the Intent specifies {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+ * or would otherwise be launched in to a new task, then the activity not launched but
+ * this task be brought to the foreground and a new intent delivered to the top
+ * activity if appropriate.
*
- * <p>See {@link Activity#startActivity(android.content.Intent, android.os.Bundle)
- * Activity.startActivity} for more information.</p>
+ * <p>In other words, you generally want to use an Intent here that does not specify
+ * {@link Intent#FLAG_ACTIVITY_NEW_TASK} or {@link Intent#FLAG_ACTIVITY_NEW_DOCUMENT},
+ * and let the system do the right thing.</p>
*
* @param intent The Intent describing the new activity to be launched on the task.
* @param options Optional launch options.
+ *
+ * @see Activity#startActivity(android.content.Intent, android.os.Bundle)
*/
public void startActivity(Context context, Intent intent, Bundle options) {
ActivityThread thread = ActivityThread.currentActivityThread();
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1f7e450..394b183 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -509,8 +509,7 @@
case ACTIVITY_PAUSED_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
- PersistableBundle persistentState = data.readPersistableBundle();
- activityPaused(token, persistentState);
+ activityPaused(token);
reply.writeNoException();
return true;
}
@@ -2829,13 +2828,12 @@
data.recycle();
reply.recycle();
}
- public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException
+ public void activityPaused(IBinder token) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
- data.writePersistableBundle(persistentState);
mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9dd4605..213c7f6 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -84,13 +84,13 @@
* Initial width of the animation.
* @hide
*/
- public static final String KEY_ANIM_START_WIDTH = "android:animStartWidth";
+ public static final String KEY_ANIM_WIDTH = "android:animWidth";
/**
* Initial height of the animation.
* @hide
*/
- public static final String KEY_ANIM_START_HEIGHT = "android:animStartHeight";
+ public static final String KEY_ANIM_HEIGHT = "android:animHeight";
/**
* Callback for when animation is started.
@@ -140,8 +140,8 @@
private Bitmap mThumbnail;
private int mStartX;
private int mStartY;
- private int mStartWidth;
- private int mStartHeight;
+ private int mWidth;
+ private int mHeight;
private IRemoteCallback mAnimationStartedListener;
private ResultReceiver mTransitionReceiver;
private boolean mIsReturning;
@@ -238,13 +238,13 @@
* defines the coordinate space for <var>startX</var> and <var>startY</var>.
* @param startX The x starting location of the new activity, relative to <var>source</var>.
* @param startY The y starting location of the activity, relative to <var>source</var>.
- * @param startWidth The initial width of the new activity.
- * @param startHeight The initial height of the new activity.
+ * @param width The initial width of the new activity.
+ * @param height The initial height of the new activity.
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
*/
public static ActivityOptions makeScaleUpAnimation(View source,
- int startX, int startY, int startWidth, int startHeight) {
+ int startX, int startY, int width, int height) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = ANIM_SCALE_UP;
@@ -252,8 +252,8 @@
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
- opts.mStartWidth = startWidth;
- opts.mStartHeight = startHeight;
+ opts.mWidth = width;
+ opts.mHeight = height;
return opts;
}
@@ -359,9 +359,10 @@
* @hide
*/
public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
- Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
- true);
+ Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+ targetWidth, targetHeight, listener, true);
}
/**
@@ -382,13 +383,15 @@
* @hide
*/
public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
- Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
- return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
- false);
+ Bitmap thumbnail, int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY,
+ targetWidth, targetHeight, listener, false);
}
private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
- int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+ int startX, int startY, int targetWidth, int targetHeight,
+ OnAnimationStartedListener listener, boolean scaleUp) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
@@ -398,6 +401,8 @@
source.getLocationOnScreen(pts);
opts.mStartX = pts[0] + startX;
opts.mStartY = pts[1] + startY;
+ opts.mWidth = targetWidth;
+ opts.mHeight = targetHeight;
opts.setOnAnimationStartedListener(source.getHandler(), listener);
return opts;
}
@@ -515,11 +520,6 @@
return opts;
}
- @Deprecated
- public static ActivityOptions makeLaunchTaskBehindAnimation() {
- return makeTaskLaunchBehind();
- }
-
/** @hide */
public boolean getLaunchTaskBehind() {
return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -543,8 +543,8 @@
case ANIM_SCALE_UP:
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
- mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
- mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
+ mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+ mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
break;
case ANIM_THUMBNAIL_SCALE_UP:
@@ -554,6 +554,8 @@
mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
+ mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
+ mHeight = opts.getInt(KEY_ANIM_HEIGHT, 0);
mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
opts.getBinder(KEY_ANIM_START_LISTENER));
break;
@@ -605,13 +607,13 @@
}
/** @hide */
- public int getStartWidth() {
- return mStartWidth;
+ public int getWidth() {
+ return mWidth;
}
/** @hide */
- public int getStartHeight() {
- return mStartHeight;
+ public int getHeight() {
+ return mHeight;
}
/** @hide */
@@ -690,8 +692,8 @@
case ANIM_SCALE_UP:
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
- mStartWidth = otherOptions.mStartWidth;
- mStartHeight = otherOptions.mStartHeight;
+ mWidth = otherOptions.mWidth;
+ mHeight = otherOptions.mHeight;
if (mAnimationStartedListener != null) {
try {
mAnimationStartedListener.sendResult(null);
@@ -707,6 +709,8 @@
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
+ mWidth = otherOptions.mWidth;
+ mHeight = otherOptions.mHeight;
if (mAnimationStartedListener != null) {
try {
mAnimationStartedListener.sendResult(null);
@@ -755,8 +759,8 @@
case ANIM_SCALE_UP:
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
- b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
- b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
+ b.putInt(KEY_ANIM_WIDTH, mWidth);
+ b.putInt(KEY_ANIM_HEIGHT, mHeight);
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -765,6 +769,8 @@
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
+ b.putInt(KEY_ANIM_WIDTH, mWidth);
+ b.putInt(KEY_ANIM_HEIGHT, mHeight);
b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
!= null ? mAnimationStartedListener.asBinder() : null);
break;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 38999a8..3a39900 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -563,11 +563,11 @@
}
public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) {
+ boolean userLeaving, int configChanges, boolean dontReport) {
sendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
- (userLeaving ? 1 : 0),
+ (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
configChanges);
}
@@ -1283,13 +1283,15 @@
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
- handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
+ handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
+ (msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
- handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
+ handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
+ (msg.arg1&1) != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_SHOW:
@@ -1938,7 +1940,7 @@
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
- printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
+ printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "",
"Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------", "------");
@@ -3142,7 +3144,7 @@
}
private void handlePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) {
+ boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
@@ -3159,9 +3161,11 @@
}
// Tell the activity manager we have paused.
- try {
- ActivityManagerNative.getDefault().activityPaused(token, r.persistentState);
- } catch (RemoteException ex) {
+ if (!dontReport) {
+ try {
+ ActivityManagerNative.getDefault().activityPaused(token);
+ } catch (RemoteException ex) {
+ }
}
mSomeActivitiesChanged = true;
}
@@ -4283,6 +4287,8 @@
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
+
/*
* Before spawning a new process, reset the time zone to be the system time zone.
* This needs to be done because the system time zone could have changed after the
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index a09a2e7..9f49194 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -197,7 +197,7 @@
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
final protected ArrayList<String> mSharedElementNames = new ArrayList<String>();
final protected ArrayList<View> mTransitioningViews = new ArrayList<View>();
- protected SharedElementListener mListener;
+ protected SharedElementCallback mListener;
protected ResultReceiver mResultReceiver;
final private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
final protected boolean mIsReturning;
@@ -205,10 +205,11 @@
private boolean mIsStartingTransition;
private ArrayList<GhostViewListeners> mGhostViewListeners =
new ArrayList<GhostViewListeners>();
+ private ArrayMap<View, Float> mOriginalAlphas = new ArrayMap<View, Float>();
public ActivityTransitionCoordinator(Window window,
ArrayList<String> allSharedElementNames,
- SharedElementListener listener, boolean isReturning) {
+ SharedElementCallback listener, boolean isReturning) {
super(new Handler());
mWindow = window;
mListener = listener;
@@ -218,7 +219,7 @@
protected void viewsReady(ArrayMap<String, View> sharedElements) {
sharedElements.retainAll(mAllSharedElementNames);
- mListener.remapSharedElements(mAllSharedElementNames, sharedElements);
+ mListener.onMapSharedElements(mAllSharedElementNames, sharedElements);
mSharedElementNames.addAll(sharedElements.keySet());
mSharedElements.addAll(sharedElements.values());
if (getViewsTransition() != null) {
@@ -251,9 +252,11 @@
*/
protected void setEpicenter() {
View epicenter = null;
- if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty() &&
- mAllSharedElementNames.get(0).equals(mSharedElementNames.get(0))) {
- epicenter = mSharedElements.get(0);
+ if (!mAllSharedElementNames.isEmpty() && !mSharedElementNames.isEmpty()) {
+ int index = mSharedElementNames.indexOf(mAllSharedElementNames.get(0));
+ if (index >= 0) {
+ epicenter = mSharedElements.get(index);
+ }
}
setEpicenter(epicenter);
}
@@ -458,20 +461,21 @@
tempMatrix, tempRect, null);
}
}
- mListener.setSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
+ mListener.onSharedElementStart(mSharedElementNames, mSharedElements, snapshots);
return originalImageState;
}
protected void notifySharedElementEnd(ArrayList<View> snapshots) {
- mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
+ mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, snapshots);
}
protected void scheduleSetSharedElementEnd(final ArrayList<View> snapshots) {
- getDecor().getViewTreeObserver().addOnPreDrawListener(
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
notifySharedElementEnd(snapshots);
return true;
}
@@ -526,7 +530,7 @@
Parcelable parcelable = sharedElementBundle.getParcelable(KEY_SNAPSHOT);
View snapshot = null;
if (parcelable != null) {
- snapshot = mListener.createSnapshotView(context, parcelable);
+ snapshot = mListener.onCreateSnapshotView(context, parcelable);
}
if (snapshot != null) {
setSharedElementState(snapshot, name, state, null, null, decorLoc);
@@ -577,6 +581,7 @@
mWindow = null;
mSharedElements.clear();
mTransitioningViews.clear();
+ mOriginalAlphas.clear();
mResultReceiver = null;
mPendingTransition = null;
mListener = null;
@@ -586,10 +591,27 @@
return getWindow().getTransitionBackgroundFadeDuration();
}
- protected static void setTransitionAlpha(ArrayList<View> views, float alpha) {
+ protected void hideViews(ArrayList<View> views) {
int count = views.size();
for (int i = 0; i < count; i++) {
- views.get(i).setTransitionAlpha(alpha);
+ View view = views.get(i);
+ if (!mOriginalAlphas.containsKey(view)) {
+ mOriginalAlphas.put(view, view.getAlpha());
+ }
+ view.setAlpha(0f);
+ view.setTransitionAlpha(0f);
+ }
+ }
+
+ protected void showViews(ArrayList<View> views) {
+ int count = views.size();
+ for (int i = 0; i < count; i++) {
+ View view = views.get(i);
+ Float alpha = mOriginalAlphas.remove(view);
+ if (alpha != null) {
+ view.setAlpha(alpha);
+ view.setTransitionAlpha(1f);
+ }
}
}
@@ -618,7 +640,7 @@
sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
sharedElementBundle.putFloat(KEY_ELEVATION, view.getElevation());
- Parcelable bitmap = mListener.captureSharedElementSnapshot(view, tempMatrix, tempBounds);
+ Parcelable bitmap = mListener.onCaptureSharedElementSnapshot(view, tempMatrix, tempBounds);
if (bitmap != null) {
sharedElementBundle.putParcelable(KEY_SNAPSHOT, bitmap);
}
@@ -664,8 +686,7 @@
GhostView.addGhost(view, decor);
ViewGroup parent = (ViewGroup) view.getParent();
if (moveWithParent && !isInTransitionGroup(parent, decor)) {
- GhostViewListeners listener =
- new GhostViewListeners(view, decor);
+ GhostViewListeners listener = new GhostViewListeners(view, parent, decor);
parent.getViewTreeObserver().addOnPreDrawListener(listener);
mGhostViewListeners.add(listener);
}
@@ -723,11 +744,12 @@
}
protected void scheduleGhostVisibilityChange(final int visibility) {
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
setGhostVisibility(visibility);
return true;
}
@@ -769,10 +791,12 @@
private static class GhostViewListeners implements ViewTreeObserver.OnPreDrawListener {
private View mView;
private ViewGroup mDecor;
+ private View mParent;
private Matrix mMatrix = new Matrix();
- public GhostViewListeners(View view, ViewGroup decor) {
+ public GhostViewListeners(View view, View parent, ViewGroup decor) {
mView = view;
+ mParent = parent;
mDecor = decor;
}
@@ -782,10 +806,9 @@
@Override
public boolean onPreDraw() {
- ViewGroup parent = ((ViewGroup) mView.getParent());
GhostView ghostView = GhostView.getGhost(mView);
if (ghostView == null) {
- parent.getViewTreeObserver().removeOnPreDrawListener(this);
+ mParent.getViewTreeObserver().removeOnPreDrawListener(this);
} else {
GhostView.calculateMatrix(mView, mDecor, mMatrix);
ghostView.setMatrix(mMatrix);
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index a64e0ed..2c596e5 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -385,6 +386,7 @@
}
/** @hide */
+ @SystemApi
public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
PendingIntent operation, WorkSource workSource) {
setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6843827..404268c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -45,14 +45,17 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -864,6 +867,49 @@
return getApplicationLogo(getApplicationInfo(packageName, 0));
}
+ @Override
+ public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
+ final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
+ if (badgeResId == 0) {
+ return icon;
+ }
+ Drawable badgeIcon = getDrawable("system", badgeResId, null);
+ return getBadgedDrawable(icon, badgeIcon, null, true);
+ }
+
+ @Override
+ public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
+ Rect badgeLocation, int badgeDensity) {
+ Drawable badgeDrawable = getUserBadgeForDensity(user, badgeDensity);
+ if (badgeDrawable == null) {
+ return drawable;
+ }
+ return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+ }
+
+ @Override
+ public Drawable getUserBadgeForDensity(UserHandle user, int density) {
+ UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+ if (userInfo != null && userInfo.isManagedProfile()) {
+ if (density <= 0) {
+ density = mContext.getResources().getDisplayMetrics().densityDpi;
+ }
+ return Resources.getSystem().getDrawableForDensity(
+ com.android.internal.R.drawable.ic_corp_badge, density);
+ }
+ return null;
+ }
+
+ @Override
+ public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
+ UserInfo userInfo = getUserIfProfile(user.getIdentifier());
+ if (userInfo != null && userInfo.isManagedProfile()) {
+ return Resources.getSystem().getString(
+ com.android.internal.R.string.managed_profile_label_badge, label);
+ }
+ return label;
+ }
+
@Override public Resources getResourcesForActivity(
ComponentName activityName) throws NameNotFoundException {
return getResourcesForApplication(
@@ -1640,12 +1686,86 @@
if (itemInfo.showUserIcon != UserHandle.USER_NULL) {
return new BitmapDrawable(getUserManager().getUserIcon(itemInfo.showUserIcon));
}
- Drawable dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+ Drawable dr = null;
+ if (itemInfo.packageName != null) {
+ dr = getDrawable(itemInfo.packageName, itemInfo.icon, appInfo);
+ }
if (dr == null) {
dr = itemInfo.loadDefaultIcon(this);
}
- return getUserManager().getBadgedDrawableForUser(dr,
- new UserHandle(mContext.getUserId()));
+ return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId()));
+ }
+
+ private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable,
+ Rect badgeLocation, boolean tryBadgeInPlace) {
+ final int badgedWidth = drawable.getIntrinsicWidth();
+ final int badgedHeight = drawable.getIntrinsicHeight();
+ final boolean canBadgeInPlace = tryBadgeInPlace
+ && (drawable instanceof BitmapDrawable)
+ && ((BitmapDrawable) drawable).getBitmap().isMutable();
+
+ final Bitmap bitmap;
+ if (canBadgeInPlace) {
+ bitmap = ((BitmapDrawable) drawable).getBitmap();
+ } else {
+ bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Bitmap.Config.ARGB_8888);
+ }
+ Canvas canvas = new Canvas(bitmap);
+
+ if (!canBadgeInPlace) {
+ drawable.setBounds(0, 0, badgedWidth, badgedHeight);
+ drawable.draw(canvas);
+ }
+
+ if (badgeLocation != null) {
+ if (badgeLocation.left < 0 || badgeLocation.top < 0
+ || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
+ throw new IllegalArgumentException("Badge location " + badgeLocation
+ + " not in badged drawable bounds "
+ + new Rect(0, 0, badgedWidth, badgedHeight));
+ }
+ badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
+
+ canvas.save();
+ canvas.translate(badgeLocation.left, badgeLocation.top);
+ badgeDrawable.draw(canvas);
+ canvas.restore();
+ } else {
+ badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
+ badgeDrawable.draw(canvas);
+ }
+
+ if (!canBadgeInPlace) {
+ BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
+
+ if (drawable instanceof BitmapDrawable) {
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
+ mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
+ }
+
+ return mergedDrawable;
+ }
+
+ return drawable;
+ }
+
+ private int getBadgeResIdForUser(int userHandle) {
+ // Return the framework-provided badge.
+ UserInfo userInfo = getUserIfProfile(userHandle);
+ if (userInfo != null && userInfo.isManagedProfile()) {
+ return com.android.internal.R.drawable.ic_corp_icon_badge;
+ }
+ return 0;
+ }
+
+ private UserInfo getUserIfProfile(int userHandle) {
+ List<UserInfo> userProfiles = getUserManager().getProfiles(UserHandle.myUserId());
+ for (UserInfo user : userProfiles) {
+ if (user.id == userHandle) {
+ return user;
+ }
+ }
+ return null;
}
private final ContextImpl mContext;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 63e8707..0123e16 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -78,7 +78,8 @@
boolean finished = data.readInt() != 0;
boolean userLeaving = data.readInt() != 0;
int configChanges = data.readInt();
- schedulePauseActivity(b, finished, userLeaving, configChanges);
+ boolean dontReport = data.readInt() != 0;
+ schedulePauseActivity(b, finished, userLeaving, configChanges, dontReport);
return true;
}
@@ -689,13 +690,14 @@
}
public final void schedulePauseActivity(IBinder token, boolean finished,
- boolean userLeaving, int configChanges) throws RemoteException {
+ boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(finished ? 1 : 0);
data.writeInt(userLeaving ? 1 :0);
data.writeInt(configChanges);
+ data.writeInt(dontReport ? 1 : 0);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 59f010c..8227915 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -1128,11 +1128,11 @@
}
if (isBack) {
- outFragment.mEnterTransitionListener.remapSharedElements(
+ outFragment.mEnterTransitionCallback.onMapSharedElements(
mSharedElementTargetNames, namedViews);
setBackNameOverrides(state, namedViews, false);
} else {
- outFragment.mExitTransitionListener.remapSharedElements(
+ outFragment.mExitTransitionCallback.onMapSharedElements(
mSharedElementTargetNames, namedViews);
setNameOverrides(state, namedViews, false);
}
@@ -1248,14 +1248,14 @@
}
// Notify the start of the transition.
- SharedElementListener listener = isBack ?
- outFragment.mEnterTransitionListener :
- inFragment.mEnterTransitionListener;
+ SharedElementCallback callback = isBack ?
+ outFragment.mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
tempNames.clear();
tempNames.addAll(namedViews.keySet());
tempViewList.clear();
tempViewList.addAll(namedViews.values());
- listener.setSharedElementStart(tempNames, tempViewList, null);
+ callback.onSharedElementStart(tempNames, tempViewList, null);
// Set the epicenter of the exit transition
if (mSharedElementTargetNames != null && exitTransition != null) {
@@ -1337,11 +1337,11 @@
tempViews2, isBack);
// remap shared elements and set the name mapping used in the shared element transition.
if (isBack) {
- inFragment.mExitTransitionListener.remapSharedElements(
+ inFragment.mExitTransitionCallback.onMapSharedElements(
mSharedElementTargetNames, namedViews);
setBackNameOverrides(state, namedViews, true);
} else {
- inFragment.mEnterTransitionListener.remapSharedElements(
+ inFragment.mEnterTransitionCallback.onMapSharedElements(
mSharedElementTargetNames, namedViews);
setNameOverrides(state, namedViews, true);
}
@@ -1355,14 +1355,14 @@
}
int containerId = inFragments.keyAt(i);
- SharedElementListener sharedElementListener = isBack ?
- outFragments.get(containerId).mEnterTransitionListener :
- inFragment.mEnterTransitionListener;
+ SharedElementCallback sharedElementCallback = isBack ?
+ outFragments.get(containerId).mEnterTransitionCallback :
+ inFragment.mEnterTransitionCallback;
tempNames.clear();
tempNames.addAll(namedViews.keySet());
tempViews.clear();
tempViews.addAll(namedViews.values());
- sharedElementListener.setSharedElementEnd(tempNames, tempViews, null);
+ sharedElementCallback.onSharedElementEnd(tempNames, tempViews, null);
}
// Don't include any newly-hidden fragments in the transition.
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 4126647..f38c108 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -21,8 +21,6 @@
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.os.ResultReceiver;
import android.text.TextUtils;
import android.transition.Transition;
@@ -71,12 +69,13 @@
Bundle resultReceiverBundle = new Bundle();
resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
- getDecor().getViewTreeObserver().addOnPreDrawListener(
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (mIsReadyForTransition) {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
}
return mIsReadyForTransition;
}
@@ -113,9 +112,9 @@
protected void viewsReady(ArrayMap<String, View> sharedElements) {
super.viewsReady(sharedElements);
mIsReadyForTransition = true;
- setTransitionAlpha(mSharedElements, 0);
+ hideViews(mSharedElements);
if (getViewsTransition() != null) {
- setTransitionAlpha(mTransitioningViews, 0);
+ hideViews(mTransitioningViews);
}
if (mIsReturning) {
sendSharedElementDestination();
@@ -189,11 +188,12 @@
moveSharedElementsToOverlay();
mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
} else {
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
if (mResultReceiver != null) {
Bundle state = captureSharedElementState();
setSharedElementMatrices();
@@ -209,7 +209,7 @@
}
}
- private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+ private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
}
@@ -240,7 +240,7 @@
if (!mIsCanceled) {
mIsCanceled = true;
if (getViewsTransition() == null || mIsViewsTransitionStarted) {
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements);
} else {
mTransitioningViews.addAll(mSharedElements);
}
@@ -294,13 +294,13 @@
ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames);
rejectedNames.removeAll(mSharedElementNames);
ArrayList<View> rejectedSnapshots = createSnapshots(sharedElementState, rejectedNames);
- mListener.handleRejectedSharedElements(rejectedSnapshots);
+ mListener.onRejectSharedElements(rejectedSnapshots);
startRejectedAnimations(rejectedSnapshots);
// Now start shared element transition
ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
mSharedElementNames);
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements);
scheduleSetSharedElementEnd(sharedElementSnapshots);
ArrayList<SharedElementOriginalState> originalImageViewState =
setSharedElementState(sharedElementState, sharedElementSnapshots);
@@ -344,11 +344,12 @@
}
final Bundle sharedElementState = mSharedElementsBundle;
mSharedElementsBundle = null;
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
startTransition(new Runnable() {
@Override
public void run() {
@@ -358,7 +359,7 @@
return false;
}
});
- getDecor().invalidate();
+ decorView.invalidate();
}
private void requestLayoutForSharedElements() {
@@ -410,7 +411,7 @@
@Override
public void onTransitionStart(Transition transition) {
mEnterViewsTransition = transition;
- setTransitionAlpha(mTransitioningViews, 1);
+ showViews(mTransitioningViews);
super.onTransitionStart(transition);
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 231c93f..982bbc4 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -79,7 +79,7 @@
mActivity = activity;
}
- private static SharedElementListener getListener(Activity activity, boolean isReturning) {
+ private static SharedElementCallback getListener(Activity activity, boolean isReturning) {
return isReturning ? activity.mEnterTransitionListener : activity.mExitTransitionListener;
}
@@ -126,8 +126,8 @@
}
public void resetViews() {
- setTransitionAlpha(mTransitioningViews, 1);
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mTransitioningViews);
+ showViews(mSharedElements);
mIsHidden = true;
if (!mIsReturning && getDecor() != null) {
getDecor().suppressLayout(false);
@@ -165,18 +165,19 @@
});
final ArrayList<View> sharedElementSnapshots = createSnapshots(mExitSharedElementBundle,
mSharedElementNames);
- getDecor().getViewTreeObserver()
+ final View decorView = getDecor();
+ decorView.getViewTreeObserver()
.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ decorView.getViewTreeObserver().removeOnPreDrawListener(this);
setSharedElementState(mExitSharedElementBundle, sharedElementSnapshots);
return true;
}
});
setGhostVisibility(View.INVISIBLE);
scheduleGhostVisibilityChange(View.INVISIBLE);
- mListener.setSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
+ mListener.onSharedElementEnd(mSharedElementNames, mSharedElements, sharedElementSnapshots);
TransitionManager.beginDelayedTransition(getDecor(), transition);
scheduleGhostVisibilityChange(View.VISIBLE);
setGhostVisibility(View.VISIBLE);
@@ -186,7 +187,7 @@
private void hideSharedElements() {
moveSharedElementsFromOverlay();
if (!mIsHidden) {
- setTransitionAlpha(mSharedElements, 0);
+ hideViews(mSharedElements);
}
mSharedElementsHidden = true;
finishIfNecessary();
@@ -295,7 +296,7 @@
transition.removeListener(this);
exitTransitionComplete();
if (mIsHidden) {
- setTransitionAlpha(mTransitioningViews, 1);
+ showViews(mTransitioningViews);
}
if (mSharedElementBundle != null) {
delayCancel();
@@ -322,7 +323,7 @@
transition.removeListener(this);
sharedElementTransitionComplete();
if (mIsHidden) {
- setTransitionAlpha(mSharedElements, 1);
+ showViews(mSharedElements);
}
}
});
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index dbee81e..672ef7b 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -495,8 +495,8 @@
private Boolean mAllowReturnTransitionOverlap;
private Boolean mAllowEnterTransitionOverlap;
- SharedElementListener mEnterTransitionListener = SharedElementListener.NULL_LISTENER;
- SharedElementListener mExitTransitionListener = SharedElementListener.NULL_LISTENER;
+ SharedElementCallback mEnterTransitionCallback = SharedElementCallback.NULL_CALLBACK;
+ SharedElementCallback mExitTransitionCallback = SharedElementCallback.NULL_CALLBACK;
/**
* State information that has been retrieved from a fragment instance
@@ -1621,31 +1621,31 @@
}
/**
- * When custom transitions are used with Fragments, the enter transition listener
+ * When custom transitions are used with Fragments, the enter transition callback
* is called when this Fragment is attached or detached when not popping the back stack.
*
- * @param listener Used to manipulate the shared element transitions on this Fragment
+ * @param callback Used to manipulate the shared element transitions on this Fragment
* when added not as a pop from the back stack.
*/
- public void setEnterSharedElementTransitionListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setEnterSharedElementTransitionCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mEnterTransitionListener = listener;
+ mEnterTransitionCallback = callback;
}
/**
- * When custom transitions are used with Fragments, the exit transition listener
+ * When custom transitions are used with Fragments, the exit transition callback
* is called when this Fragment is attached or detached when popping the back stack.
*
- * @param listener Used to manipulate the shared element transitions on this Fragment
+ * @param callback Used to manipulate the shared element transitions on this Fragment
* when added as a pop from the back stack.
*/
- public void setExitSharedElementTransitionListener(SharedElementListener listener) {
- if (listener == null) {
- listener = SharedElementListener.NULL_LISTENER;
+ public void setExitSharedElementTransitionCallback(SharedElementCallback callback) {
+ if (callback == null) {
+ callback = SharedElementCallback.NULL_CALLBACK;
}
- mExitTransitionListener = listener;
+ mExitTransitionCallback = callback;
}
/**
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 99428e8..9483680 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -111,7 +111,7 @@
public void activityResumed(IBinder token) throws RemoteException;
public void activityIdle(IBinder token, Configuration config,
boolean stopProfiling) throws RemoteException;
- public void activityPaused(IBinder token, PersistableBundle persistentState) throws RemoteException;
+ public void activityPaused(IBinder token) throws RemoteException;
public void activityStopped(IBinder token, Bundle state,
PersistableBundle persistentState, CharSequence description) throws RemoteException;
public void activitySlept(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a7546d9..f53075c 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -49,7 +49,7 @@
*/
public interface IApplicationThread extends IInterface {
void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
- int configChanges) throws RemoteException;
+ int configChanges, boolean dontReport) throws RemoteException;
void scheduleStopActivity(IBinder token, boolean showWindow,
int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index dbd180f..7d4512b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -48,6 +48,9 @@
void setPackagePriority(String pkg, int uid, int priority);
int getPackagePriority(String pkg, int uid);
+ void setPackageVisibilityOverride(String pkg, int uid, int visibility);
+ int getPackageVisibilityOverride(String pkg, int uid);
+
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
StatusBarNotification[] getActiveNotifications(String callingPkg);
@@ -68,6 +71,7 @@
ComponentName getEffectsSuppressor();
boolean matchesCallFilter(in Bundle extras);
+ boolean matchesCallFilterAsUser(in Bundle extras, int userId);
ZenModeConfig getZenModeConfig();
boolean setZenModeConfig(in ZenModeConfig config);
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 181eb63..3b5900b 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -16,6 +16,7 @@
package android.app;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.app.IWallpaperManagerCallback;
@@ -73,6 +74,11 @@
int getHeightHint();
/**
+ * Sets extra padding that we would like the wallpaper to have outside of the display.
+ */
+ void setDisplayPadding(in Rect padding);
+
+ /**
* Returns the name of the wallpaper. Private API.
*/
String getName();
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index e055237..cc9aed8 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -56,13 +56,6 @@
public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION";
/**
- * @removed
- */
- public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
- return createConfirmDeviceCredentialIntent(title, description);
- }
-
- /**
* Get an intent to prompt the user to confirm credentials (pin, pattern or password)
* for the current user of the device. The caller is expected to launch this activity using
* {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ebeaf34..2476c4b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -37,7 +38,6 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
-import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.MathUtils;
@@ -129,6 +129,14 @@
public static final int DEFAULT_LIGHTS = 4;
/**
+ * Maximum length of CharSequences accepted by Builder and friends.
+ *
+ * <p>
+ * Avoids spamming the system with overly large strings such as full e-mails.
+ */
+ private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
+
+ /**
* A timestamp related to this notification, in milliseconds since the epoch.
*
* Default value: {@link System#currentTimeMillis() Now}.
@@ -537,8 +545,26 @@
*/
public int visibility;
+ /**
+ * Notification visibility: Show this notification in its entirety on all lockscreens.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_PUBLIC = 1;
+
+ /**
+ * Notification visibility: Show this notification on all lockscreens, but conceal sensitive or
+ * private information on secure lockscreens.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_PRIVATE = 0;
+
+ /**
+ * Notification visibility: Do not reveal any part of this notification on a secure lockscreen.
+ *
+ * {@see #visibility}
+ */
public static final int VISIBILITY_SECRET = -1;
/**
@@ -816,13 +842,6 @@
public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
/**
- * {@link #extras} key: the user that built the notification.
- *
- * @hide
- */
- public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
-
- /**
* Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
* displayed in the heads up space.
*
@@ -1435,6 +1454,10 @@
* @hide
*/
public static CharSequence safeCharSequence(CharSequence cs) {
+ if (cs == null) return cs;
+ if (cs.length() > MAX_CHARSEQUENCE_LENGTH) {
+ cs = cs.subSequence(0, MAX_CHARSEQUENCE_LENGTH);
+ }
if (cs instanceof Parcelable) {
Log.e(TAG, "warning: " + cs.getClass().getCanonicalName()
+ " instance is a custom Parcelable and not allowed in Notification");
@@ -1801,10 +1824,12 @@
= "android.rebuild.hudViewActionCount";
/**
- * The package name of the context used to create the notification via a Builder.
+ * The ApplicationInfo of the package that created the notification, used to create
+ * a context to rebuild the notification via a Builder.
+ * @hide
*/
- private static final String EXTRA_REBUILD_CONTEXT_PACKAGE =
- "android.rebuild.contextPackage";
+ private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO =
+ "android.rebuild.applicationInfo";
// Whether to enable stripping (at post time) & rebuilding (at listener receive time) of
// memory intensive resources.
@@ -1855,11 +1880,6 @@
private int mColor = COLOR_DEFAULT;
/**
- * The user that built the notification originally.
- */
- private int mOriginatingUserId;
-
- /**
* Contains extras related to rebuilding during the build phase.
*/
private Bundle mRebuildBundle = new Bundle();
@@ -2578,8 +2598,8 @@
private Drawable getProfileBadgeDrawable() {
// Note: This assumes that the current user can read the profile badge of the
// originating user.
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+ return mContext.getPackageManager().getUserBadgeForDensity(
+ new UserHandle(mContext.getUserId()), 0);
}
private Bitmap getProfileBadge() {
@@ -2658,8 +2678,7 @@
* @param hasProgress whether the progress bar should be shown and set
*/
private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
- RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
- mOriginatingUserId, resId);
+ RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
resetStandardTemplate(contentView);
@@ -3051,8 +3070,8 @@
*/
public void populateExtras(Bundle extras) {
// Store original information used in the construction of this object
- extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
- extras.putString(EXTRA_REBUILD_CONTEXT_PACKAGE, mContext.getPackageName());
+ extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
+ mContext.getApplicationInfo());
extras.putCharSequence(EXTRA_TITLE, mContentTitle);
extras.putCharSequence(EXTRA_TEXT, mContentText);
extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
@@ -3140,13 +3159,14 @@
extras.remove(EXTRA_NEEDS_REBUILD);
// Re-create notification context so we can access app resources.
- String packageName = extras.getString(EXTRA_REBUILD_CONTEXT_PACKAGE);
+ ApplicationInfo applicationInfo = extras.getParcelable(
+ EXTRA_REBUILD_CONTEXT_APPLICATION_INFO);
Context builderContext;
try {
- builderContext = context.createPackageContext(packageName,
+ builderContext = context.createApplicationContext(applicationInfo,
Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) {
- Log.e(TAG, "Package name " + packageName + " not found");
+ Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found");
builderContext = context; // try with our context
}
@@ -3281,7 +3301,6 @@
// Extras.
Bundle extras = n.extras;
- mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
mContentTitle = extras.getCharSequence(EXTRA_TITLE);
mContentText = extras.getCharSequence(EXTRA_TEXT);
mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3314,7 +3333,6 @@
* object.
*/
public Notification build() {
- mOriginatingUserId = mContext.getUserId();
mHasThreeLines = hasThreeLines();
Notification n = buildUnstyled();
@@ -3386,8 +3404,16 @@
*/
public static abstract class Style {
private CharSequence mBigContentTitle;
- private CharSequence mSummaryText = null;
- private boolean mSummaryTextSet = false;
+
+ /**
+ * @hide
+ */
+ protected CharSequence mSummaryText = null;
+
+ /**
+ * @hide
+ */
+ protected boolean mSummaryTextSet = false;
protected Builder mBuilder;
@@ -3679,6 +3705,11 @@
* @see Notification#bigContentView
*/
public static class BigTextStyle extends Style {
+
+ private static final int MAX_LINES = 13;
+ private static final int LINES_CONSUMED_BY_ACTIONS = 3;
+ private static final int LINES_CONSUMED_BY_SUMMARY = 2;
+
private CharSequence mBigText;
public BigTextStyle() {
@@ -3745,6 +3776,7 @@
contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
+ contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines());
contentView.setViewVisibility(R.id.text2, View.GONE);
applyTopPadding(contentView);
@@ -3756,6 +3788,24 @@
return contentView;
}
+ private int calculateMaxLines() {
+ int lineCount = MAX_LINES;
+ boolean hasActions = mBuilder.mActions.size() > 0;
+ boolean hasSummary = (mSummaryTextSet ? mSummaryText : mBuilder.mSubText) != null;
+ if (hasActions) {
+ lineCount -= LINES_CONSUMED_BY_ACTIONS;
+ }
+ if (hasSummary) {
+ lineCount -= LINES_CONSUMED_BY_SUMMARY;
+ }
+
+ // If we have less top padding at the top, we can fit less lines.
+ if (!mBuilder.mHasThreeLines) {
+ lineCount--;
+ }
+ return lineCount;
+ }
+
/**
* @hide
*/
@@ -4814,8 +4864,8 @@
super(parcel);
}
- public BuilderRemoteViews(String packageName, int userId, int layoutId) {
- super(packageName, userId, layoutId);
+ public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) {
+ super(appInfo, layoutId);
}
@Override
diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementCallback.java
similarity index 64%
rename from core/java/android/app/SharedElementListener.java
rename to core/java/android/app/SharedElementCallback.java
index f36d05f..82d8e5b 100644
--- a/core/java/android/app/SharedElementListener.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -22,7 +22,6 @@
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.os.Parcelable;
import android.view.View;
@@ -31,28 +30,23 @@
/**
* Listener provided in
- * {@link Activity#setEnterSharedElementListener(SharedElementListener)} and
- * {@link Activity#setExitSharedElementListener(SharedElementListener)}
- * to monitor the Activity transitions. The events can be used to customize Activity
- * Transition behavior.
+ * {@link Activity#setEnterSharedElementCallback(SharedElementCallback)} and
+ * {@link Activity#setExitSharedElementCallback(SharedElementCallback)} as well as
+ * {@link Fragment#setEnterSharedElementTransitionCallback(SharedElementCallback)} and
+ * {@link Fragment#setExitSharedElementTransitionCallback(SharedElementCallback)}
+ * to monitor the Shared element transitions. The events can be used to customize Activity
+ * and Fragment Transition behavior.
*/
-public abstract class SharedElementListener {
+public abstract class SharedElementCallback {
private Matrix mTempMatrix;
- static final SharedElementListener NULL_LISTENER = new SharedElementListener() {
+ static final SharedElementCallback NULL_CALLBACK = new SharedElementCallback() {
};
/**
- * Called to allow the listener to customize the start state of the shared element when
- * transferring in shared element state.
- * <p>
- * The shared element will start at the size and position of the shared element
- * in the launching Activity or Fragment. It will also transfer ImageView scaleType
- * and imageMatrix if the shared elements in the calling and called Activities are
- * ImageViews. Some applications may want to make additional changes, such as
- * changing the clip bounds, scaling, or rotation if the shared element end state
- * does not map well to the start state.
- * </p>
+ * Called immediately after the start state is set for the shared element.
+ * The shared element will start at the size and position of the shared element
+ * in the launching Activity or Fragment.
*
* @param sharedElementNames The names of the shared elements that were accepted into
* the View hierarchy.
@@ -60,20 +54,21 @@
* @param sharedElementSnapshots The Views containing snap shots of the shared element
* from the launching Window. These elements will not
* be part of the scene, but will be positioned relative
- * to the Window decor View.
+ * to the Window decor View. This list is null for Fragment
+ * Transitions.
*/
- public void setSharedElementStart(List<String> sharedElementNames,
+ public void onSharedElementStart(List<String> sharedElementNames,
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called to allow the listener to customize the end state of the shared element when
- * transferring in shared element state.
+ * Called after the end state is set for the shared element, but before the end state
+ * is captured by the shared element transition.
* <p>
* Any customization done in
- * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)}
+ * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)}
* may need to be modified to the final state of the shared element if it is not
* automatically corrected by layout. For example, rotation or scale will not
- * be affected by layout and if changed in {@link #setSharedElementStart(java.util.List,
+ * be affected by layout and if changed in {@link #onSharedElementStart(java.util.List,
* java.util.List, java.util.List)}, it will also have to be set here again to correct
* the end state.
* </p>
@@ -84,24 +79,27 @@
* @param sharedElementSnapshots The Views containing snap shots of the shared element
* from the launching Window. These elements will not
* be part of the scene, but will be positioned relative
- * to the Window decor View.
+ * to the Window decor View. This list will be null for
+ * Fragment Transitions.
*/
- public void setSharedElementEnd(List<String> sharedElementNames,
+ public void onSharedElementEnd(List<String> sharedElementNames,
List<View> sharedElements, List<View> sharedElementSnapshots) {}
/**
- * Called after {@link #remapSharedElements(java.util.List, java.util.Map)} when
+ * Called after {@link #onMapSharedElements(java.util.List, java.util.Map)} when
* transferring shared elements in. Any shared elements that have no mapping will be in
* <var>rejectedSharedElements</var>. The elements remaining in
* <var>rejectedSharedElements</var> will be transitioned out of the Scene. If a
* View is removed from <var>rejectedSharedElements</var>, it must be handled by the
- * <code>SharedElementListener</code>.
+ * <code>SharedElementCallback</code>.
* <p>
* Views in rejectedSharedElements will have their position and size set to the
* position of the calling shared element, relative to the Window decor View and contain
* snapshots of the View from the calling Activity or Fragment. This
* view may be safely added to the decor View's overlay to remain in position.
* </p>
+ * <p>This method is not called for Fragment Transitions. All rejected shared elements
+ * will be handled by the exit transition.</p>
*
* @param rejectedSharedElements Views containing visual information of shared elements
* that are not part of the entering scene. These Views
@@ -109,25 +107,27 @@
* View removed from this list will not be transitioned
* automatically.
*/
- public void handleRejectedSharedElements(List<View> rejectedSharedElements) {}
+ public void onRejectSharedElements(List<View> rejectedSharedElements) {}
/**
- * Lets the ActivityTransitionListener adjust the mapping of shared element names to
+ * Lets the SharedElementCallback adjust the mapping of shared element names to
* Views.
*
* @param names The names of all shared elements transferred from the calling Activity
- * to the started Activity.
+ * or Fragment in the order they were provided.
* @param sharedElements The mapping of shared element names to Views. The best guess
* will be filled into sharedElements based on the transitionNames.
*/
- public void remapSharedElements(List<String> names, Map<String, View> sharedElements) {}
+ public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {}
/**
* Creates a snapshot of a shared element to be used by the remote Activity and reconstituted
- * with {@link #createSnapshotView(android.content.Context, android.os.Parcelable)}. A
+ * with {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)}. A
* null return value will mean that the remote Activity will have a null snapshot View in
- * {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
- * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ * {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+ * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ *
+ * <p>This is not called for Fragment Transitions.</p>
*
* @param sharedElement The shared element View to create a snapshot for.
* @param viewToGlobalMatrix A matrix containing a transform from the view to the screen
@@ -135,11 +135,11 @@
* @param screenBounds The bounds of shared element in screen coordinate space. This is
* the bounds of the view with the viewToGlobalMatrix applied.
* @return A snapshot to send to the remote Activity to be reconstituted with
- * {@link #createSnapshotView(android.content.Context, android.os.Parcelable)} and passed
- * into {@link #setSharedElementStart(java.util.List, java.util.List, java.util.List)} and
- * {@link #setSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
+ * {@link #onCreateSnapshotView(android.content.Context, android.os.Parcelable)} and passed
+ * into {@link #onSharedElementStart(java.util.List, java.util.List, java.util.List)} and
+ * {@link #onSharedElementEnd(java.util.List, java.util.List, java.util.List)}.
*/
- public Parcelable captureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
+ public Parcelable onCaptureSharedElementSnapshot(View sharedElement, Matrix viewToGlobalMatrix,
RectF screenBounds) {
int bitmapWidth = Math.round(screenBounds.width());
int bitmapHeight = Math.round(screenBounds.height());
@@ -160,20 +160,22 @@
/**
* Reconstitutes a snapshot View from a Parcelable returned in
- * {@link #captureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
- * android.graphics.RectF)} to be used in {@link #setSharedElementStart(java.util.List,
- * java.util.List, java.util.List)} and {@link #setSharedElementEnd(java.util.List,
+ * {@link #onCaptureSharedElementSnapshot(android.view.View, android.graphics.Matrix,
+ * android.graphics.RectF)} to be used in {@link #onSharedElementStart(java.util.List,
+ * java.util.List, java.util.List)} and {@link #onSharedElementEnd(java.util.List,
* java.util.List, java.util.List)}. The returned View will be sized and positioned after
* this call so that it is ready to be added to the decor View's overlay.
*
+ * <p>This is not called for Fragment Transitions.</p>
+ *
* @param context The Context used to create the snapshot View.
- * @param snapshot The Parcelable returned by {@link #captureSharedElementSnapshot(
+ * @param snapshot The Parcelable returned by {@link #onCaptureSharedElementSnapshot(
* android.view.View, android.graphics.Matrix, android.graphics.RectF)}.
- * @return A View to be sent in {@link #setSharedElementStart(java.util.List, java.util.List,
- * java.util.List)} and {@link #setSharedElementEnd(java.util.List, java.util.List,
+ * @return A View to be sent in {@link #onSharedElementStart(java.util.List, java.util.List,
+ * java.util.List)} and {@link #onSharedElementEnd(java.util.List, java.util.List,
* java.util.List)}. A null value will produce a null snapshot value for those two methods.
*/
- public View createSnapshotView(Context context, Parcelable snapshot) {
+ public View onCreateSnapshotView(Context context, Parcelable snapshot) {
View view = null;
if (snapshot instanceof Bitmap) {
Bitmap bitmap = (Bitmap) snapshot;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 48ff5b6..8bfe6d3 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -951,6 +952,48 @@
}
/**
+ * Specify extra padding that the wallpaper should have outside of the display.
+ * That is, the given padding supplies additional pixels the wallpaper should extend
+ * outside of the display itself.
+ * @param padding The number of pixels the wallpaper should extend beyond the display,
+ * on its left, top, right, and bottom sides.
+ * @hide
+ */
+ @SystemApi
+ public void setDisplayPadding(Rect padding) {
+ try {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ } else {
+ sGlobals.mService.setDisplayPadding(padding);
+ }
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+
+ /**
+ * Apply a raw offset to the wallpaper window. Should only be used in
+ * combination with {@link #setDisplayPadding(android.graphics.Rect)} when you
+ * have ensured that the wallpaper will extend outside of the display area so that
+ * it can be moved without leaving part of the display uncovered.
+ * @param x The offset, in pixels, to apply to the left edge.
+ * @param y The offset, in pixels, to apply to the top edge.
+ * @hide
+ */
+ @SystemApi
+ public void setDisplayOffset(IBinder windowToken, int x, int y) {
+ try {
+ //Log.v(TAG, "Sending new wallpaper display offsets from app...");
+ WindowManagerGlobal.getWindowSession().setWallpaperDisplayOffset(
+ windowToken, x, y);
+ //Log.v(TAG, "...app returning after sending display offset!");
+ } catch (RemoteException e) {
+ // Ignore.
+ }
+ }
+
+ /**
* Set the position of the current wallpaper within any larger space, when
* that wallpaper is visible behind the given window. The X and Y offsets
* are floating point numbers ranging from 0 to 1, representing where the
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 15def09..e2f175c 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -177,7 +177,7 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_ENTERING
- = "android.app.action.ACTION_LOCK_TASK_ENTERING";
+ = "android.app.action.LOCK_TASK_ENTERING";
/**
* Action sent to a device administrator to notify that the device is exiting
@@ -190,7 +190,7 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_LOCK_TASK_EXITING
- = "android.app.action.ACTION_LOCK_TASK_EXITING";
+ = "android.app.action.LOCK_TASK_EXITING";
/**
* A boolean describing whether the device is currently entering or exiting
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 282444a..926a348 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -125,7 +125,7 @@
* during the managed profile provisioning.
*/
public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
- "android.app.extra.ADMIN_EXTRA_BUNDLE";
+ "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
/**
* A String extra holding the package name of the mobile device management application that
@@ -148,21 +148,15 @@
* <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
*/
public static final String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME
- = "android.app.extra.DEFAULT_MANAGED_PROFILE_NAME";
+ = "android.app.extra.PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME";
/**
- * A String extra that, holds the email address of the account which a managed profile is
- * created for. Used with {@link #ACTION_PROVISION_MANAGED_PROFILE} and
- * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}.
- *
- * <p> If the {@link #ACTION_PROVISION_MANAGED_PROFILE} intent that starts managed provisioning
- * contains this extra, it is forwarded in the
- * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} intent to the mobile
- * device management application that was set as the profile owner during provisioning.
- * It is usually used to avoid that the user has to enter their email address twice.
+ * A bundle key, used in the bundle extra {@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}. The
+ * corresponding value holds the email address of the account which the managed profile is
+ * created for.
*/
- public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
- = "android.app.extra.ManagedProfileEmailAddress";
+ public static final String KEY_PROVISIONING_EMAIL_ADDRESS
+ = "android.app.key.PROVISIONING_EMAIL_ADDRESS";
/**
* A String extra holding the time zone {@link android.app.AlarmManager} that the device
@@ -172,7 +166,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_TIME_ZONE
- = "android.app.extra.TIME_ZONE";
+ = "android.app.extra.PROVISIONING_TIME_ZONE";
/**
* A Long extra holding the wall clock time (in milliseconds) to be set on the device's
@@ -182,7 +176,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCAL_TIME
- = "android.app.extra.LOCAL_TIME";
+ = "android.app.extra.PROVISIONING_LOCAL_TIME";
/**
* A String extra holding the {@link java.util.Locale} that the device will be set to.
@@ -192,7 +186,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_LOCALE
- = "android.app.extra.LOCALE";
+ = "android.app.extra.PROVISIONING_LOCALE";
/**
* A String extra holding the ssid of the wifi network that should be used during nfc device
@@ -202,7 +196,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SSID
- = "android.app.extra.WIFI_SSID";
+ = "android.app.extra.PROVISIONING_WIFI_SSID";
/**
* A boolean extra indicating whether the wifi network in {@link #EXTRA_PROVISIONING_WIFI_SSID}
@@ -212,7 +206,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_HIDDEN
- = "android.app.extra.WIFI_HIDDEN";
+ = "android.app.extra.PROVISIONING_WIFI_HIDDEN";
/**
* A String extra indicating the security type of the wifi network in
@@ -222,7 +216,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE
- = "android.app.extra.WIFI_SECURITY_TYPE";
+ = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
/**
* A String extra holding the password of the wifi network in
@@ -232,7 +226,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PASSWORD
- = "android.app.extra.WIFI_PASSWORD";
+ = "android.app.extra.PROVISIONING_WIFI_PASSWORD";
/**
* A String extra holding the proxy host for the wifi network in
@@ -242,7 +236,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_HOST
- = "android.app.extra.WIFI_PROXY_HOST";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_HOST";
/**
* An int extra holding the proxy port for the wifi network in
@@ -252,7 +246,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_PORT
- = "android.app.extra.WIFI_PROXY_PORT";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
/**
* A String extra holding the proxy bypass for the wifi network in
@@ -262,7 +256,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PROXY_BYPASS
- = "android.app.extra.WIFI_PROXY_BYPASS_HOSTS";
+ = "android.app.extra.PROVISIONING_WIFI_PROXY_BYPASS";
/**
* A String extra holding the proxy auto-config (PAC) URL for the wifi network in
@@ -272,7 +266,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_WIFI_PAC_URL
- = "android.app.extra.WIFI_PAC_URL";
+ = "android.app.extra.PROVISIONING_WIFI_PAC_URL";
/**
* A String extra holding a url that specifies the download location of the device admin
@@ -282,7 +276,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
/**
* A String extra holding a http cookie header which should be used in the http request to the
@@ -292,7 +286,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
/**
* A String extra holding the SHA-1 checksum of the file at download location specified in
@@ -304,7 +298,7 @@
* provisioning via an Nfc bump.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
+ = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
/**
* This MIME type is used for starting the Device Owner provisioning.
@@ -447,13 +441,13 @@
* Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from a
* managed profile to its parent.
*/
- public static int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
+ public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 0x0001;
/**
* Flag used by {@link #addCrossProfileIntentFilter} to allow access of certain intents from the
* parent to its managed profile.
*/
- public static int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
+ public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
/**
* Return true if the given administrator component is currently
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 1bb4eba..9151a16 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -218,6 +218,7 @@
*/
@SystemApi
public boolean isBackupEnabled() {
+ checkServiceBinder();
if (sService != null) {
try {
return sService.isBackupEnabled();
diff --git a/core/java/android/app/usage/ConfigurationStats.java b/core/java/android/app/usage/ConfigurationStats.java
new file mode 100644
index 0000000..080216c
--- /dev/null
+++ b/core/java/android/app/usage/ConfigurationStats.java
@@ -0,0 +1,161 @@
+/**
+ * Copyright (C) 2014 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.res.Configuration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents the usage statistics of a device {@link android.content.res.Configuration} for a
+ * specific time range.
+ */
+public final class ConfigurationStats implements Parcelable {
+
+ /**
+ * {@hide}
+ */
+ public Configuration mConfiguration;
+
+ /**
+ * {@hide}
+ */
+ public long mBeginTimeStamp;
+
+ /**
+ * {@hide}
+ */
+ public long mEndTimeStamp;
+
+ /**
+ * {@hide}
+ */
+ public long mLastTimeActive;
+
+ /**
+ * {@hide}
+ */
+ public long mTotalTimeActive;
+
+ /**
+ * {@hide}
+ */
+ public int mActivationCount;
+
+ /**
+ * {@hide}
+ */
+ public ConfigurationStats() {
+ }
+
+ public ConfigurationStats(ConfigurationStats stats) {
+ mConfiguration = stats.mConfiguration;
+ mBeginTimeStamp = stats.mBeginTimeStamp;
+ mEndTimeStamp = stats.mEndTimeStamp;
+ mLastTimeActive = stats.mLastTimeActive;
+ mTotalTimeActive = stats.mTotalTimeActive;
+ mActivationCount = stats.mActivationCount;
+ }
+
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ /**
+ * Get the beginning of the time range this {@link ConfigurationStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getFirstTimeStamp() {
+ return mBeginTimeStamp;
+ }
+
+ /**
+ * Get the end of the time range this {@link ConfigurationStats} represents,
+ * measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeStamp() {
+ return mEndTimeStamp;
+ }
+
+ /**
+ * Get the last time this configuration was active, measured in milliseconds since the epoch.
+ * <p/>
+ * See {@link System#currentTimeMillis()}.
+ */
+ public long getLastTimeActive() {
+ return mLastTimeActive;
+ }
+
+ /**
+ * Get the total time this configuration was active, measured in milliseconds.
+ */
+ public long getTotalTimeActive() {
+ return mTotalTimeActive;
+ }
+
+ /**
+ * Get the number of times this configuration was active.
+ */
+ public int getActivationCount() {
+ return mActivationCount;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mConfiguration != null) {
+ dest.writeInt(1);
+ mConfiguration.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+
+ dest.writeLong(mBeginTimeStamp);
+ dest.writeLong(mEndTimeStamp);
+ dest.writeLong(mLastTimeActive);
+ dest.writeLong(mTotalTimeActive);
+ dest.writeInt(mActivationCount);
+ }
+
+ public static final Creator<ConfigurationStats> CREATOR = new Creator<ConfigurationStats>() {
+ @Override
+ public ConfigurationStats createFromParcel(Parcel source) {
+ ConfigurationStats stats = new ConfigurationStats();
+ if (source.readInt() != 0) {
+ stats.mConfiguration = Configuration.CREATOR.createFromParcel(source);
+ }
+ stats.mBeginTimeStamp = source.readLong();
+ stats.mEndTimeStamp = source.readLong();
+ stats.mLastTimeActive = source.readLong();
+ stats.mTotalTimeActive = source.readLong();
+ stats.mActivationCount = source.readInt();
+ return stats;
+ }
+
+ @Override
+ public ConfigurationStats[] newArray(int size) {
+ return new ConfigurationStats[size];
+ }
+ };
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 3b09888..4ed1489 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -27,5 +27,7 @@
interface IUsageStatsManager {
ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime,
String callingPackage);
+ ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
+ String callingPackage);
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
}
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index fb80de2..1a947ec 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -16,6 +16,7 @@
package android.app.usage;
import android.content.ComponentName;
+import android.content.res.Configuration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -63,6 +64,11 @@
public static final int CONTINUE_PREVIOUS_DAY = 4;
/**
+ * An event type denoting that the device configuration has changed.
+ */
+ public static final int CONFIGURATION_CHANGE = 5;
+
+ /**
* {@hide}
*/
public String mPackage;
@@ -83,6 +89,12 @@
public int mEventType;
/**
+ * Only present for {@link #CONFIGURATION_CHANGE} event types.
+ * {@hide}
+ */
+ public Configuration mConfiguration;
+
+ /**
* TODO(adamlesinski): Removed before release.
* {@hide}
*/
@@ -123,6 +135,14 @@
public int getEventType() {
return mEventType;
}
+
+ /**
+ * Returns a {@link Configuration} for this event if the event is of type
+ * {@link #CONFIGURATION_CHANGE}, otherwise it returns null.
+ */
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
}
// Only used when creating the resulting events. Not used for reading/unparceling.
@@ -201,23 +221,9 @@
return false;
}
- final int packageIndex = mParcel.readInt();
- if (packageIndex >= 0) {
- eventOut.mPackage = mStringPool[packageIndex];
- } else {
- eventOut.mPackage = null;
- }
+ readEventFromParcel(mParcel, eventOut);
- final int classIndex = mParcel.readInt();
- if (classIndex >= 0) {
- eventOut.mClass = mStringPool[classIndex];
- } else {
- eventOut.mClass = null;
- }
- eventOut.mEventType = mParcel.readInt();
- eventOut.mTimeStamp = mParcel.readLong();
mIndex++;
-
if (mIndex >= mEventCount) {
mParcel.recycle();
mParcel = null;
@@ -235,11 +241,6 @@
}
}
- @Override
- public int describeContents() {
- return 0;
- }
-
private int findStringIndex(String str) {
final int index = Arrays.binarySearch(mStringPool, str);
if (index < 0) {
@@ -248,6 +249,66 @@
return index;
}
+ /**
+ * Writes a single event to the parcel. Modify this when updating {@link Event}.
+ */
+ private void writeEventToParcel(Event event, Parcel p, int flags) {
+ final int packageIndex;
+ if (event.mPackage != null) {
+ packageIndex = findStringIndex(event.mPackage);
+ } else {
+ packageIndex = -1;
+ }
+
+ final int classIndex;
+ if (event.mClass != null) {
+ classIndex = findStringIndex(event.mClass);
+ } else {
+ classIndex = -1;
+ }
+ p.writeInt(packageIndex);
+ p.writeInt(classIndex);
+ p.writeInt(event.mEventType);
+ p.writeLong(event.mTimeStamp);
+
+ if (event.mEventType == Event.CONFIGURATION_CHANGE) {
+ event.mConfiguration.writeToParcel(p, flags);
+ }
+ }
+
+ /**
+ * Reads a single event from the parcel. Modify this when updating {@link Event}.
+ */
+ private void readEventFromParcel(Parcel p, Event eventOut) {
+ final int packageIndex = p.readInt();
+ if (packageIndex >= 0) {
+ eventOut.mPackage = mStringPool[packageIndex];
+ } else {
+ eventOut.mPackage = null;
+ }
+
+ final int classIndex = p.readInt();
+ if (classIndex >= 0) {
+ eventOut.mClass = mStringPool[classIndex];
+ } else {
+ eventOut.mClass = null;
+ }
+ eventOut.mEventType = p.readInt();
+ eventOut.mTimeStamp = p.readLong();
+
+ // Extract the configuration for configuration change events.
+ if (eventOut.mEventType == Event.CONFIGURATION_CHANGE) {
+ eventOut.mConfiguration = Configuration.CREATOR.createFromParcel(p);
+ } else {
+ eventOut.mConfiguration = null;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mEventCount);
@@ -262,25 +323,9 @@
p.setDataPosition(0);
for (int i = 0; i < mEventCount; i++) {
final Event event = mEventsToWrite.get(i);
-
- final int packageIndex;
- if (event.mPackage != null) {
- packageIndex = findStringIndex(event.mPackage);
- } else {
- packageIndex = -1;
- }
-
- final int classIndex;
- if (event.mClass != null) {
- classIndex = findStringIndex(event.mClass);
- } else {
- classIndex = -1;
- }
- p.writeInt(packageIndex);
- p.writeInt(classIndex);
- p.writeInt(event.getEventType());
- p.writeLong(event.getTimeStamp());
+ writeEventToParcel(event, p, flags);
}
+
final int listByteLength = p.dataPosition();
// Write the total length of the data.
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 5830fcf..bc6099a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -125,9 +125,9 @@
* @see #INTERVAL_YEARLY
* @see #INTERVAL_BEST
*/
- @SuppressWarnings("unchecked")
public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
try {
+ @SuppressWarnings("unchecked")
ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime,
endTime, mContext.getOpPackageName());
if (slice != null) {
@@ -136,7 +136,32 @@
} catch (RemoteException e) {
// fallthrough and return null.
}
- return Collections.EMPTY_LIST;
+ return Collections.emptyList();
+ }
+
+ /**
+ * Gets the hardware configurations the device was in for the given time range, aggregated by
+ * the specified interval. The results are ordered as in
+ * {@link #queryUsageStats(int, long, long)}.
+ *
+ * @param intervalType The time interval by which the stats are aggregated.
+ * @param beginTime The inclusive beginning of the range of stats to include in the results.
+ * @param endTime The exclusive end of the range of stats to include in the results.
+ * @return A list of {@link ConfigurationStats} or null if none are available.
+ */
+ public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime,
+ long endTime) {
+ try {
+ @SuppressWarnings("unchecked")
+ ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats(
+ intervalType, beginTime, endTime, mContext.getOpPackageName());
+ if (slice != null) {
+ return slice.getList();
+ }
+ } catch (RemoteException e) {
+ // fallthrough and return the empty list.
+ }
+ return Collections.emptyList();
}
/**
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 119d705..083a48a 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -17,6 +17,7 @@
package android.app.usage;
import android.content.ComponentName;
+import android.content.res.Configuration;
/**
* UsageStatsManager local system service interface.
@@ -28,14 +29,19 @@
/**
* Reports an event to the UsageStatsManager.
*
- * @param component The component for which this event ocurred.
+ * @param component The component for which this event occurred.
* @param userId The user id to which the component belongs to.
- * @param timeStamp The time at which this event ocurred.
- * @param eventType The event that occured. Valid values can be found at
+ * @param eventType The event that occurred. Valid values can be found at
* {@link UsageEvents}
*/
- public abstract void reportEvent(ComponentName component, int userId,
- long timeStamp, int eventType);
+ public abstract void reportEvent(ComponentName component, int userId, int eventType);
+
+ /**
+ * Reports a configuration change to the UsageStatsManager.
+ *
+ * @param config The new device configuration.
+ */
+ public abstract void reportConfigurationChange(Configuration config, int userId);
/**
* Prepares the UsageStatsService for shutdown.
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index bd45c7e..00248cc 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -188,7 +188,7 @@
* this widget. Can have the value {@link
* AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
* AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
- * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
+ * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
*/
public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 02f70c8..b4d79b4 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -61,9 +61,9 @@
public static final int WIDGET_CATEGORY_KEYGUARD = 2;
/**
- * Indicates that the widget can be displayed within recents.
+ * Indicates that the widget can be displayed within a space reserved for the search box.
*/
- public static final int WIDGET_CATEGORY_RECENTS = 4;
+ public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
/**
* Identity of this AppWidget component. This component should be a {@link
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index c7bfae9..ff0db9a 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -119,8 +119,8 @@
}
AdvertiseData other = (AdvertiseData) obj;
return Objects.equals(mServiceUuids, other.mServiceUuids) &&
- Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
- Utils.equals(mServiceData, other.mServiceData) &&
+ BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
+ BluetoothLeUtils.equals(mServiceData, other.mServiceData) &&
mIncludeDeviceName == other.mIncludeDeviceName &&
mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
}
@@ -128,8 +128,8 @@
@Override
public String toString() {
return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData="
- + Utils.toString(mManufacturerSpecificData) + ", mServiceData="
- + Utils.toString(mServiceData)
+ + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
+ + BluetoothLeUtils.toString(mServiceData)
+ ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
+ mIncludeDeviceName + "]";
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 3568f26..d468508 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -107,7 +107,7 @@
AdvertiseData advertiseData, AdvertiseData scanResponse,
final AdvertiseCallback callback) {
synchronized (mLeAdvertisers) {
- checkAdapterState();
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
@@ -150,7 +150,7 @@
*/
public void stopAdvertising(final AdvertiseCallback callback) {
synchronized (mLeAdvertisers) {
- checkAdapterState();
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
@@ -265,9 +265,18 @@
}
if (mClientIf > 0 && mIsAdvertising) {
mLeAdvertisers.put(mAdvertiseCallback, this);
- } else {
+ } else if (mClientIf <= 0) {
+ // Post internal error if registration failed.
postStartFailure(mAdvertiseCallback,
AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
+ } else {
+ // Unregister application if it's already registered but advertise failed.
+ try {
+ mBluetoothGatt.unregisterClient(mClientIf);
+ mClientIf = -1;
+ } catch (RemoteException e) {
+ Log.e(TAG, "remote exception when unregistering", e);
+ }
}
}
}
@@ -342,13 +351,6 @@
}
}
- // TODO: move this api to a common util class.
- private void checkAdapterState() {
- if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) {
- throw new IllegalStateException("BT Adapter is not turned ON");
- }
- }
-
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index e1d4bbd2..a57c3ca 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -80,11 +80,10 @@
* @throws IllegalArgumentException If {@code callback} is null.
*/
public void startScan(final ScanCallback callback) {
- checkAdapterState();
if (callback == null) {
throw new IllegalArgumentException("callback is null");
}
- this.startScan(null, new ScanSettings.Builder().build(), callback);
+ startScan(null, new ScanSettings.Builder().build(), callback);
}
/**
@@ -104,7 +103,7 @@
private void startScan(List<ScanFilter> filters, ScanSettings settings,
final ScanCallback callback, List<List<ResultStorageDescriptor>> resultStorages) {
- checkAdapterState();
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (settings == null || callback == null) {
throw new IllegalArgumentException("settings or callback is null");
}
@@ -142,7 +141,7 @@
* @param callback
*/
public void stopScan(ScanCallback callback) {
- checkAdapterState();
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
synchronized (mLeScanClients) {
BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
if (wrapper == null) {
@@ -162,7 +161,7 @@
* used to start scan.
*/
public void flushPendingScanResults(ScanCallback callback) {
- checkAdapterState();
+ BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null!");
}
@@ -373,13 +372,6 @@
}
}
- // TODO: move this api to a common util class.
- private void checkAdapterState() {
- if (mBluetoothAdapter.getState() != mBluetoothAdapter.STATE_ON) {
- throw new IllegalStateException("BT Adapter is not turned ON");
- }
- }
-
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
@Override
diff --git a/core/java/android/bluetooth/le/Utils.java b/core/java/android/bluetooth/le/BluetoothLeUtils.java
similarity index 87%
rename from core/java/android/bluetooth/le/Utils.java
rename to core/java/android/bluetooth/le/BluetoothLeUtils.java
index ccdae69..4916bd9 100644
--- a/core/java/android/bluetooth/le/Utils.java
+++ b/core/java/android/bluetooth/le/BluetoothLeUtils.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.bluetooth.BluetoothAdapter;
import android.util.SparseArray;
import java.util.Arrays;
@@ -29,7 +30,7 @@
*
* @hide
*/
-public class Utils {
+public class BluetoothLeUtils {
/**
* Returns a string composed from a {@link SparseArray}.
@@ -123,4 +124,17 @@
}
return true;
}
+
+ /**
+ * Ensure Bluetooth is turned on.
+ *
+ * @throws IllegalStateException If {@code adapter} is null or Bluetooth state is not
+ * {@link BluetoothAdapter#STATE_ON}.
+ */
+ static void checkAdapterStateOn(BluetoothAdapter adapter) {
+ if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON) {
+ throw new IllegalStateException("BT Adapter is not turned ON");
+ }
+ }
+
}
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 2f3d06f..f802e8d 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -268,8 +268,8 @@
@Override
public String toString() {
return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
- + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData)
- + ", mServiceData=" + Utils.toString(mServiceData)
+ + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData)
+ + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData)
+ ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
}
diff --git a/core/java/android/content/AbstractRestrictionsProvider.java b/core/java/android/content/AbstractRestrictionsProvider.java
deleted file mode 100644
index 262980e..0000000
--- a/core/java/android/content/AbstractRestrictionsProvider.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content;
-
-import android.app.admin.DevicePolicyManager;
-import android.os.IBinder;
-import android.os.PersistableBundle;
-
-/**
- * @hide
- * Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
- * Restrictions Provider, extend from this class and implement the abstract methods.
- * Export this receiver in the manifest. A profile owner device admin can then register this
- * component as a Restrictions Provider using
- * {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
- * <p>
- * The function of a Restrictions Provider is to transport permission requests from apps on this
- * device to an administrator (most likely on a remote device or computer) and deliver back
- * responses. The response should be sent back to the app via
- * {@link RestrictionsManager#notifyPermissionResponse(String, PersistableBundle)}.
- *
- * @see RestrictionsManager
- * TODO: STOPSHIP: Remove before L ships, after clients have switched over
- * to android.service.restrictions.RestrictionsReceiver. Bug: 17006805
- */
-public abstract class AbstractRestrictionsProvider extends BroadcastReceiver {
-
- private static final String TAG = "AbstractRestrictionsProvider";
-
- /**
- * An asynchronous permission request made by an application for an operation that requires
- * authorization by a local or remote administrator other than the user. The Restrictions
- * Provider should transfer the request to the administrator and deliver back a response, when
- * available. The calling application is aware that the response could take an indefinite
- * amount of time.
- * <p>
- * If the request bundle contains the key {@link RestrictionsManager#REQUEST_KEY_NEW_REQUEST},
- * then a new request must be sent. Otherwise the provider can look up any previous response
- * to the same requestId and return the cached response.
- *
- * @param packageName the application requesting permission.
- * @param requestType the type of request, which determines the content and presentation of
- * the request data.
- * @param request the request data bundle containing at a minimum a request id.
- *
- * @see RestrictionsManager#REQUEST_TYPE_APPROVAL
- * @see RestrictionsManager#REQUEST_TYPE_LOCAL_APPROVAL
- * @see RestrictionsManager#REQUEST_KEY_ID
- */
- public abstract void requestPermission(Context context,
- String packageName, String requestType, String requestId, PersistableBundle request);
-
- /**
- * Intercept standard Restrictions Provider broadcasts. Implementations
- * should not override this method; it is better to implement the
- * convenience callbacks for each action.
- */
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
-
- if (RestrictionsManager.ACTION_REQUEST_PERMISSION.equals(action)) {
- String packageName = intent.getStringExtra(RestrictionsManager.EXTRA_PACKAGE_NAME);
- String requestType = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_TYPE);
- String requestId = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_ID);
- PersistableBundle request = (PersistableBundle)
- intent.getParcelableExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE);
- requestPermission(context, packageName, requestType, requestId, request);
- }
- }
-}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index fde8b2e..2853c58 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -639,12 +639,14 @@
* @param authorities the semi-colon separated authorities of the ContentProvider.
*/
protected final void setAuthorities(String authorities) {
- if (authorities.indexOf(';') == -1) {
- mAuthority = authorities;
- mAuthorities = null;
- } else {
- mAuthority = null;
- mAuthorities = authorities.split(";");
+ if (authorities != null) {
+ if (authorities.indexOf(';') == -1) {
+ mAuthority = authorities;
+ mAuthorities = null;
+ } else {
+ mAuthority = null;
+ mAuthorities = authorities.split(";");
+ }
}
}
@@ -653,9 +655,11 @@
if (mAuthority != null) {
return mAuthority.equals(authority);
}
- int length = mAuthorities.length;
- for (int i = 0; i < length; i++) {
- if (mAuthorities[i].equals(authority)) return true;
+ if (mAuthorities != null) {
+ int length = mAuthorities.length;
+ for (int i = 0; i < length; i++) {
+ if (mAuthorities[i].equals(authority)) return true;
+ }
}
return false;
}
diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl
index 495ac2e..db9146f 100644
--- a/core/java/android/content/IRestrictionsManager.aidl
+++ b/core/java/android/content/IRestrictionsManager.aidl
@@ -30,5 +30,5 @@
void requestPermission(in String packageName, in String requestType, in String requestId,
in PersistableBundle requestData);
void notifyPermissionResponse(in String packageName, in PersistableBundle response);
- Intent getLocalApprovalIntent();
+ Intent createLocalApprovalIntent();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b825c94..ff9f6ab 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1213,6 +1213,13 @@
= "android.intent.extra.ASSIST_CONTEXT";
/**
+ * An optional field on {@link #ACTION_ASSIST} suggesting that the user will likely use a
+ * keyboard as the primary input device for assistance.
+ */
+ public static final String EXTRA_ASSIST_INPUT_HINT_KEYBOARD =
+ "android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
+
+ /**
* Activity Action: List all available applications
* <p>Input: Nothing.
* <p>Output: nothing.
@@ -3363,7 +3370,7 @@
* profiles - {@link #ACTION_MANAGED_PROFILE_ADDED} and {@link #ACTION_MANAGED_PROFILE_REMOVED}.
*/
public static final String EXTRA_USER =
- "android.intent.extra.user";
+ "android.intent.extra.USER";
/**
* Extra used in the response from a BroadcastReceiver that handles
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 849df55..21a6a0d 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -155,7 +155,7 @@
* The intent must contain {@link #EXTRA_REQUEST_BUNDLE} as an extra and the bundle must
* contain at least {@link #REQUEST_KEY_MESSAGE} for the activity to display.
* <p>
- * @see #getLocalApprovalIntent()
+ * @see #createLocalApprovalIntent()
*/
public static final String ACTION_REQUEST_LOCAL_APPROVAL =
"android.content.action.REQUEST_LOCAL_APPROVAL";
@@ -473,10 +473,10 @@
}
}
- public Intent getLocalApprovalIntent() {
+ public Intent createLocalApprovalIntent() {
try {
if (mService != null) {
- return mService.getLocalApprovalIntent();
+ return mService.createLocalApprovalIntent();
}
} catch (RemoteException re) {
Log.w(TAG, "Couldn't reach service");
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index dbf49c5..8d3126d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -255,16 +255,22 @@
* Bit in {@link #flags}: If set, a task rooted at this activity will have its
* baseIntent replaced by the activity immediately above this. Each activity may further
* relinquish its identity to the activity above it using this flag. Set from the
- * android.R.attr#relinquishTaskIdentity attribute.
+ * {@link android.R.attr#relinquishTaskIdentity} attribute.
*/
public static final int FLAG_RELINQUISH_TASK_IDENTITY = 0x1000;
/**
* Bit in {@link #flags} indicating that tasks started with this activity are to be
* removed from the recent list of tasks when the last activity in the task is finished.
- * {@link android.R.attr#autoRemoveFromRecents}
+ * Corresponds to {@link android.R.attr#autoRemoveFromRecents}
*/
public static final int FLAG_AUTO_REMOVE_FROM_RECENTS = 0x2000;
/**
+ * Bit in {@link #flags} indicating that this activity can start is creation/resume
+ * while the previous activity is still pausing. Corresponds to
+ * {@link android.R.attr#resumeWhilePausing}
+ */
+ public static final int FLAG_RESUME_WHILE_PAUSING = 0x4000;
+ /**
* @hide Bit in {@link #flags}: If set, this component will only be seen
* by the primary user. Only works with broadcast receivers. Set from the
* android.R.attr#primaryUserOnly attribute.
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index c6c0ff6..6daefc8 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -22,14 +22,21 @@
import android.content.pm.PackageInstaller;
import android.content.IntentSender;
+import android.graphics.Bitmap;
+
/** {@hide} */
interface IPackageInstaller {
int createSession(in PackageInstaller.SessionParams params, String installerPackageName, int userId);
+
+ void updateSessionAppIcon(int sessionId, in Bitmap appIcon);
+ void updateSessionAppLabel(int sessionId, String appLabel);
+
void abandonSession(int sessionId);
IPackageInstallerSession openSession(int sessionId);
PackageInstaller.SessionInfo getSessionInfo(int sessionId);
+
List<PackageInstaller.SessionInfo> getAllSessions(int userId);
List<PackageInstaller.SessionInfo> getMySessions(String installerPackageName, int userId);
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index 39ae1a0..974eb1e 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -19,8 +19,8 @@
/** {@hide} */
oneway interface IPackageInstallerCallback {
void onSessionCreated(int sessionId);
- void onSessionOpened(int sessionId);
+ void onSessionBadgingChanged(int sessionId);
+ void onSessionActiveChanged(int sessionId, boolean active);
void onSessionProgressChanged(int sessionId, float progress);
- void onSessionClosed(int sessionId);
void onSessionFinished(int sessionId, boolean success);
}
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 0cff08b..ee23fcd 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -18,16 +18,10 @@
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Bitmap.Config;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.DisplayMetrics;
@@ -39,11 +33,9 @@
* and badged icon for the activity.
*/
public class LauncherActivityInfo {
- private static final boolean DEBUG = false;
private static final String TAG = "LauncherActivityInfo";
private final PackageManager mPm;
- private final UserManager mUm;
private ActivityInfo mActivityInfo;
private ComponentName mComponentName;
@@ -68,7 +60,6 @@
LauncherActivityInfo(Context context) {
mPm = context.getPackageManager();
- mUm = UserManager.get(context);
}
/**
@@ -179,7 +170,7 @@
}
if (originalIcon instanceof BitmapDrawable) {
- return mUm.getBadgedIconForUser(originalIcon, mUser);
+ return mPm.getUserBadgedIcon(originalIcon, mUser);
} else {
Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index f9370b3..d49bc50 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -278,21 +278,21 @@
/**
- * Adds a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in current and managed profiles.
*
- * @param callback The callback to add.
+ * @param callback The callback to register.
*/
- public void addCallback(Callback callback) {
- addCallback(callback, null);
+ public void registerCallback(Callback callback) {
+ registerCallback(callback, null);
}
/**
- * Adds a callback for changes to packages in current and managed profiles.
+ * Registers a callback for changes to packages in current and managed profiles.
*
- * @param callback The callback to add.
+ * @param callback The callback to register.
* @param handler that should be used to post callbacks on, may be null.
*/
- public void addCallback(Callback callback, Handler handler) {
+ public void registerCallback(Callback callback, Handler handler) {
synchronized (this) {
if (callback != null && !mCallbacks.contains(callback)) {
boolean addedFirstCallback = mCallbacks.size() == 0;
@@ -308,12 +308,12 @@
}
/**
- * Removes a callback that was previously added.
+ * Unregisters a callback that was previously registered.
*
- * @param callback The callback to remove.
- * @see #addCallback(Callback)
+ * @param callback The callback to unregister.
+ * @see #registerCallback(Callback)
*/
- public void removeCallback(Callback callback) {
+ public void unregisterCallback(Callback callback) {
synchronized (this) {
removeCallbackLocked(callback);
if (mCallbacks.size() == 0) {
@@ -500,44 +500,12 @@
}
}
- /** Remove after unbundled apps have migrated STOP SHIP */
- public static abstract class OnAppsChangedCallback extends Callback {
+ /** STOPSHIP remove when launcher 3 has been updated */
+ public void addCallback(Callback callback) {
+ registerCallback(callback);
}
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback) {
- addCallback(callback, null);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void addOnAppsChangedCallback(OnAppsChangedCallback callback, Handler handler) {
- addCallback(callback, handler);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void removeOnAppsChangedCallback(OnAppsChangedCallback callback) {
- removeCallback(callback);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void startActivityForProfile(ComponentName component, UserHandle user, Rect sourceBounds,
- Bundle opts) {
- startMainActivity(component, user, sourceBounds, opts);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public void showAppDetailsForProfile(ComponentName component, UserHandle user,
- Rect sourceBounds, Bundle opts) {
- startAppDetailsActivity(component, user, sourceBounds, opts);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
- return isPackageEnabled(packageName, user);
- }
-
- /** Remove after unbundled apps have migrated STOP SHIP */
- public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
- return isActivityEnabled(component, user);
+ /** STOPSHIP remove when launcher 3 has been updated */
+ public void removeCallback(Callback callback) {
+ unregisterCallback(callback);
}
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 44e24b1..06d4c4a 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -285,6 +285,9 @@
*
* @throws IOException if parameters were unsatisfiable, such as lack of
* disk space or unavailable media.
+ * @throws SecurityException when installation services are unavailable,
+ * such as when called from a restricted user.
+ * @throws IllegalArgumentException when {@link SessionParams} is invalid.
* @return positive, non-zero unique ID that represents the created session.
* This ID remains consistent across device reboots until the
* session is finalized. IDs are not reused during a given boot.
@@ -303,15 +306,64 @@
/**
* Open an existing session to actively perform work. To succeed, the caller
* must be the owner of the install session.
+ *
+ * @throws IOException if parameters were unsatisfiable, such as lack of
+ * disk space or unavailable media.
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
*/
- public @NonNull Session openSession(int sessionId) {
+ public @NonNull Session openSession(int sessionId) throws IOException {
try {
return new Session(mInstaller.openSession(sessionId));
+ } catch (RuntimeException e) {
+ ExceptionUtils.maybeUnwrapIOException(e);
+ throw e;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
+ /**
+ * Update the icon representing the app being installed in a specific
+ * session. This should be roughly
+ * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
+ */
+ public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
+ try {
+ mInstaller.updateSessionAppIcon(sessionId, appIcon);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Update the label representing the app being installed in a specific
+ * session.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
+ */
+ public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
+ try {
+ final String val = (appLabel != null) ? appLabel.toString() : null;
+ mInstaller.updateSessionAppLabel(sessionId, val);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Completely abandon the given session, destroying all staged data and
+ * rendering it invalid. Abandoned sessions will be reported to
+ * {@link SessionCallback} listeners as failures. This is equivalent to
+ * opening the session and calling {@link Session#abandon()}.
+ *
+ * @throws SecurityException when the caller does not own the session, or
+ * the session is invalid.
+ */
public void abandonSession(int sessionId) {
try {
mInstaller.abandonSession(sessionId);
@@ -321,8 +373,11 @@
}
/**
- * Return details for a specific session. To succeed, the caller must either
- * own this session, or be the current home app.
+ * Return details for a specific session. No special permissions are
+ * required to retrieve these details.
+ *
+ * @return details for the requested session, or {@code null} if the session
+ * does not exist.
*/
public @Nullable SessionInfo getSessionInfo(int sessionId) {
try {
@@ -333,13 +388,12 @@
}
/**
- * Return list of all active install sessions, regardless of the installer.
- * To succeed, the caller must be the current home app.
+ * Return list of all known install sessions, regardless of the installer.
*/
public @NonNull List<SessionInfo> getAllSessions() {
final ApplicationInfo info = mContext.getApplicationInfo();
if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400070) {
+ && info.versionCode <= 300400110) {
Log.d(TAG, "Ignoring callback request from old prebuilt");
return Collections.EMPTY_LIST;
}
@@ -352,7 +406,7 @@
}
/**
- * Return list of all install sessions owned by the calling app.
+ * Return list of all known install sessions owned by the calling app.
*/
public @NonNull List<SessionInfo> getMySessions() {
try {
@@ -406,27 +460,38 @@
public abstract void onCreated(int sessionId);
/**
- * Session has been opened. A session is usually opened when the
- * installer is actively writing data.
+ * Badging details for an existing session has changed. For example, the
+ * app icon or label has been updated.
*/
- public abstract void onOpened(int sessionId);
+ public abstract void onBadgingChanged(int sessionId);
+
+ /**
+ * Active state for session has been changed.
+ * <p>
+ * A session is considered active whenever there is ongoing forward
+ * progress being made, such as the installer holding an open
+ * {@link Session} instance while streaming data into place, or the
+ * system optimizing code as the result of
+ * {@link Session#commit(IntentSender)}.
+ * <p>
+ * If the installer closes the {@link Session} without committing, the
+ * session is considered inactive until the installer opens the session
+ * again.
+ */
+ public abstract void onActiveChanged(int sessionId, boolean active);
/**
* Progress for given session has been updated.
* <p>
* Note that this progress may not directly correspond to the value
- * reported by {@link PackageInstaller.Session#setProgress(float)}, as
- * the system may carve out a portion of the overall progress to
- * represent its own internal installation work.
+ * reported by
+ * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+ * system may carve out a portion of the overall progress to represent
+ * its own internal installation work.
*/
public abstract void onProgressChanged(int sessionId, float progress);
/**
- * Session has been closed.
- */
- public abstract void onClosed(int sessionId);
-
- /**
* Session has completely finished, either with success or failure.
*/
public abstract void onFinished(int sessionId, boolean success);
@@ -436,9 +501,9 @@
private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
Handler.Callback {
private static final int MSG_SESSION_CREATED = 1;
- private static final int MSG_SESSION_OPENED = 2;
- private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
- private static final int MSG_SESSION_CLOSED = 4;
+ private static final int MSG_SESSION_BADGING_CHANGED = 2;
+ private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
private static final int MSG_SESSION_FINISHED = 5;
final SessionCallback mCallback;
@@ -451,21 +516,23 @@
@Override
public boolean handleMessage(Message msg) {
+ final int sessionId = msg.arg1;
switch (msg.what) {
case MSG_SESSION_CREATED:
- mCallback.onCreated(msg.arg1);
+ mCallback.onCreated(sessionId);
return true;
- case MSG_SESSION_OPENED:
- mCallback.onOpened(msg.arg1);
+ case MSG_SESSION_BADGING_CHANGED:
+ mCallback.onBadgingChanged(sessionId);
+ return true;
+ case MSG_SESSION_ACTIVE_CHANGED:
+ final boolean active = msg.arg2 != 0;
+ mCallback.onActiveChanged(sessionId, active);
return true;
case MSG_SESSION_PROGRESS_CHANGED:
- mCallback.onProgressChanged(msg.arg1, (float) msg.obj);
- return true;
- case MSG_SESSION_CLOSED:
- mCallback.onClosed(msg.arg1);
+ mCallback.onProgressChanged(sessionId, (float) msg.obj);
return true;
case MSG_SESSION_FINISHED:
- mCallback.onFinished(msg.arg1, msg.arg2 != 0);
+ mCallback.onFinished(sessionId, msg.arg2 != 0);
return true;
}
return false;
@@ -477,8 +544,14 @@
}
@Override
- public void onSessionOpened(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
+ public void onSessionBadgingChanged(int sessionId) {
+ mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
+ }
+
+ @Override
+ public void onSessionActiveChanged(int sessionId, boolean active) {
+ mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
+ .sendToTarget();
}
@Override
@@ -488,37 +561,44 @@
}
@Override
- public void onSessionClosed(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget();
- }
-
- @Override
public void onSessionFinished(int sessionId, boolean success) {
mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
.sendToTarget();
}
}
- /**
- * Register to watch for session lifecycle events. To succeed, the caller
- * must be the current home app.
- */
+ /** {@hide} */
+ @Deprecated
public void addSessionCallback(@NonNull SessionCallback callback) {
- addSessionCallback(callback, new Handler());
+ registerSessionCallback(callback);
}
/**
- * Register to watch for session lifecycle events. To succeed, the caller
- * must be the current home app.
+ * Register to watch for session lifecycle events. No special permissions
+ * are required to watch for these events.
+ */
+ public void registerSessionCallback(@NonNull SessionCallback callback) {
+ registerSessionCallback(callback, new Handler());
+ }
+
+ /** {@hide} */
+ @Deprecated
+ public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+ registerSessionCallback(callback, handler);
+ }
+
+ /**
+ * Register to watch for session lifecycle events. No special permissions
+ * are required to watch for these events.
*
* @param handler to dispatch callback events through, otherwise uses
* calling thread.
*/
- public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+ public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
// TODO: remove this temporary guard once we have new prebuilts
final ApplicationInfo info = mContext.getApplicationInfo();
if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400070) {
+ && info.versionCode <= 300400110) {
Log.d(TAG, "Ignoring callback request from old prebuilt");
return;
}
@@ -535,10 +615,16 @@
}
}
- /**
- * Unregister an existing callback.
- */
+ /** {@hide} */
+ @Deprecated
public void removeSessionCallback(@NonNull SessionCallback callback) {
+ unregisterSessionCallback(callback);
+ }
+
+ /**
+ * Unregister a previously registered callback.
+ */
+ public void unregisterSessionCallback(@NonNull SessionCallback callback) {
synchronized (mDelegates) {
for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
final SessionCallbackDelegate delegate = i.next();
@@ -574,10 +660,22 @@
mSession = session;
}
- /**
- * Set current progress. Valid values are anywhere between 0 and 1.
- */
+ /** {@hide} */
+ @Deprecated
public void setProgress(float progress) {
+ setStagingProgress(progress);
+ }
+
+ /**
+ * Set current progress of staging this session. Valid values are
+ * anywhere between 0 and 1.
+ * <p>
+ * Note that this progress may not directly correspond to the value
+ * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
+ * the system may carve out a portion of the overall progress to
+ * represent its own internal installation work.
+ */
+ public void setStagingProgress(float progress) {
try {
mSession.setClientProgress(progress);
} catch (RemoteException e) {
@@ -617,6 +715,12 @@
* start at the beginning of the file.
* @param lengthBytes total size of the file being written, used to
* preallocate the underlying disk space, or -1 if unknown.
+ * The system may clear various caches as needed to allocate
+ * this space.
+ * @throws IOException if trouble opening the file for writing, such as
+ * lack of disk space or unavailable media.
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull OutputStream openWrite(@NonNull String name, long offsetBytes,
long lengthBytes) throws IOException {
@@ -650,6 +754,9 @@
* <p>
* This returns all names which have been previously written through
* {@link #openWrite(String, long, long)} as part of this session.
+ *
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull String[] getNames() throws IOException {
try {
@@ -669,6 +776,9 @@
* through {@link #openWrite(String, long, long)} as part of this
* session. For example, this stream may be used to calculate a
* {@link MessageDigest} of a written APK before committing.
+ *
+ * @throws SecurityException if called after the session has been
+ * committed or abandoned.
*/
public @NonNull InputStream openRead(@NonNull String name) throws IOException {
try {
@@ -690,6 +800,9 @@
* Once this method is called, no additional mutations may be performed
* on the session. If the device reboots before the session has been
* finalized, you may commit the session again.
+ *
+ * @throws SecurityException if streams opened through
+ * {@link #openWrite(String, long, long)} are still open.
*/
public void commit(@NonNull IntentSender statusReceiver) {
try {
@@ -714,7 +827,9 @@
/**
* Completely abandon this session, destroying all staged data and
- * rendering it invalid.
+ * rendering it invalid. Abandoned sessions will be reported to
+ * {@link SessionCallback} listeners as failures. This is equivalent to
+ * opening the session and calling {@link Session#abandon()}.
*/
public void abandon() {
try {
@@ -868,6 +983,18 @@
}
/** {@hide} */
+ public void setInstallFlagsInternal() {
+ installFlags |= PackageManager.INSTALL_INTERNAL;
+ installFlags &= ~PackageManager.INSTALL_EXTERNAL;
+ }
+
+ /** {@hide} */
+ public void setInstallFlagsExternal() {
+ installFlags |= PackageManager.INSTALL_EXTERNAL;
+ installFlags &= ~PackageManager.INSTALL_INTERNAL;
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
@@ -931,7 +1058,7 @@
/** {@hide} */
public boolean sealed;
/** {@hide} */
- public boolean open;
+ public boolean active;
/** {@hide} */
public int mode;
@@ -955,7 +1082,7 @@
resolvedBaseCodePath = source.readString();
progress = source.readFloat();
sealed = source.readInt() != 0;
- open = source.readInt() != 0;
+ active = source.readInt() != 0;
mode = source.readInt();
sizeBytes = source.readLong();
@@ -981,20 +1108,37 @@
/**
* Return current overall progress of this session, between 0 and 1.
* <p>
- * Note that this progress may not directly correspond to the value reported
- * by {@link PackageInstaller.Session#setProgress(float)}, as the system may
- * carve out a portion of the overall progress to represent its own internal
- * installation work.
+ * Note that this progress may not directly correspond to the value
+ * reported by
+ * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+ * system may carve out a portion of the overall progress to represent
+ * its own internal installation work.
*/
public float getProgress() {
return progress;
}
/**
- * Return if this session is currently open.
+ * Return if this session is currently active.
+ * <p>
+ * A session is considered active whenever there is ongoing forward
+ * progress being made, such as the installer holding an open
+ * {@link Session} instance while streaming data into place, or the
+ * system optimizing code as the result of
+ * {@link Session#commit(IntentSender)}.
+ * <p>
+ * If the installer closes the {@link Session} without committing, the
+ * session is considered inactive until the installer opens the session
+ * again.
*/
+ public boolean isActive() {
+ return active;
+ }
+
+ /** {@hide} */
+ @Deprecated
public boolean isOpen() {
- return open;
+ return isActive();
}
/**
@@ -1050,7 +1194,7 @@
dest.writeString(resolvedBaseCodePath);
dest.writeFloat(progress);
dest.writeInt(sealed ? 1 : 0);
- dest.writeInt(open ? 1 : 0);
+ dest.writeInt(active ? 1 : 0);
dest.writeInt(mode);
dest.writeLong(sizeBytes);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1b15ff5..36d15a0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -31,6 +31,7 @@
import android.content.pm.PackageParser.PackageParserException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -200,12 +201,6 @@
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
/**
- * Resolution and querying flag: do not resolve intents cross-profile.
- * @hide
- */
- public static final int NO_CROSS_PROFILE = 0x00020000;
-
- /**
* Flag for {@link addCrossProfileIntentFilter}: if this flag is set:
* when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current
* profile will be skipped.
@@ -975,6 +970,14 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device includes at least one form of audio
+ * output, such as speakers, audio jack or streaming over bluetooth
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device is capable of communicating with
* other devices via Bluetooth.
*/
@@ -1545,6 +1548,15 @@
public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
+ * The device has all of the inputs necessary to be considered a compatible game controller, or
+ * includes a compatible game controller in the box.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
+
+
+ /**
* Action to external storage service to clean out removed apps.
* @hide
*/
@@ -2422,7 +2434,6 @@
* @see #MATCH_DEFAULT_ONLY
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
- * @see #NO_CROSS_PROFILE
* @hide
*/
public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -2882,6 +2893,79 @@
throws NameNotFoundException;
/**
+ * If the target user is a managed profile of the calling user or the caller
+ * is itself a managed profile, then this returns a badged copy of the given
+ * icon to be able to distinguish it from the original icon. For badging an
+ * arbitrary drawable use {@link #getUserBadgedDrawableForDensity(
+ * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
+ * <p>
+ * If the original drawable is a BitmapDrawable and the backing bitmap is
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+ * is performed in place and the original drawable is returned.
+ * </p>
+ *
+ * @param icon The icon to badge.
+ * @param user The target user.
+ * @return A drawable that combines the original icon and a badge as
+ * determined by the system.
+ */
+ public abstract Drawable getUserBadgedIcon(Drawable icon, UserHandle user);
+
+ /**
+ * If the target user is a managed profile of the calling user or the caller
+ * is itself a managed profile, then this returns a badged copy of the given
+ * drawable allowing the user to distinguish it from the original drawable.
+ * The caller can specify the location in the bounds of the drawable to be
+ * badged where the badge should be applied as well as the density of the
+ * badge to be used.
+ * <p>
+ * If the original drawable is a BitmapDrawable and the backing bitmap is
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * is performed in place and the original drawable is returned.
+ * </p>
+ *
+ * @param drawable The drawable to badge.
+ * @param user The target user.
+ * @param badgeLocation Where in the bounds of the badged drawable to place
+ * the badge. If not provided, the badge is applied on top of the entire
+ * drawable being badged.
+ * @param badgeDensity The optional desired density for the badge as per
+ * {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+ * the density of the display is used.
+ * @return A drawable that combines the original drawable and a badge as
+ * determined by the system.
+ */
+ public abstract Drawable getUserBadgedDrawableForDensity(Drawable drawable,
+ UserHandle user, Rect badgeLocation, int badgeDensity);
+
+ /**
+ * If the target user is a managed profile of the calling user or the caller
+ * is itself a managed profile, then this returns a drawable to use as a small
+ * icon to include in a view to distinguish it from the original icon.
+ *
+ * @param user The target user.
+ * @param density The optional desired density for the badge as per
+ * {@link android.util.DisplayMetrics#densityDpi}. If not provided
+ * the density of the current display is used.
+ * @return the drawable or null if no drawable is required.
+ * @hide
+ */
+ public abstract Drawable getUserBadgeForDensity(UserHandle user, int density);
+
+ /**
+ * If the target user is a managed profile of the calling user or the caller
+ * is itself a managed profile, then this returns a copy of the label with
+ * badging for accessibility services like talkback. E.g. passing in "Email"
+ * and it might return "Work Email" for Email in the work profile.
+ *
+ * @param label The label to change.
+ * @param user The target user.
+ * @return A label that combines the original label and a badge as
+ * determined by the system.
+ */
+ public abstract CharSequence getUserBadgedLabel(CharSequence label, UserHandle user);
+
+ /**
* Retrieve text from a package. This is a low-level API used by
* the various package manager info structures (such as
* {@link ComponentInfo} to implement retrieval of their associated
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6d40dcf..ddb0a6d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1099,9 +1099,12 @@
}
}
}
- } catch (GeneralSecurityException | IOException | RuntimeException e) {
+ } catch (GeneralSecurityException e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING,
"Failed to collect certificates from " + apkPath, e);
+ } catch (IOException | RuntimeException e) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
+ "Failed to collect certificates from " + apkPath, e);
} finally {
closeQuietly(jarFile);
}
@@ -3110,6 +3113,12 @@
false)) {
a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
}
+
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestActivity_resumeWhilePausing,
+ false)) {
+ a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
+ }
} else {
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
a.info.configChanges = 0;
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index c0383a3..c03be32 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -89,6 +89,7 @@
/** User is only partially created. */
public boolean partial;
+ public boolean guestToRemove;
public UserInfo(int id, String name, int flags) {
this(id, name, null, flags);
@@ -147,6 +148,7 @@
lastLoggedInTime = orig.lastLoggedInTime;
partial = orig.partial;
profileGroupId = orig.profileGroupId;
+ guestToRemove = orig.guestToRemove;
}
public UserHandle getUserHandle() {
@@ -172,6 +174,7 @@
dest.writeLong(lastLoggedInTime);
dest.writeInt(partial ? 1 : 0);
dest.writeInt(profileGroupId);
+ dest.writeInt(guestToRemove ? 1 : 0);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -194,5 +197,6 @@
lastLoggedInTime = source.readLong();
partial = source.readInt() != 0;
profileGroupId = source.readInt();
+ guestToRemove = source.readInt() != 0;
}
}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2684e6c..e578822 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -773,6 +773,7 @@
private native final String[] getArrayStringResource(int arrayRes);
private native final int[] getArrayStringInfo(int arrayRes);
/*package*/ native final int[] getArrayIntResource(int arrayRes);
+ /*package*/ native final int[] getStyleAttributes(int themeRes);
private native final void init(boolean isSystem);
private native final void destroy();
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index e63fd07..27bbb24 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -16,6 +16,12 @@
package android.content.res;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Parcel;
@@ -23,7 +29,7 @@
import android.text.TextUtils;
import android.view.View;
-import java.text.Format;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;
@@ -1353,8 +1359,6 @@
* Returns a string representation of the configuration that can be parsed
* by build tools (like AAPT).
*
- *
- *
* @hide
*/
public static String resourceQualifierString(Configuration config) {
@@ -1568,4 +1572,229 @@
parts.add("v" + Build.VERSION.RESOURCES_SDK_INT);
return TextUtils.join("-", parts);
}
+
+ /**
+ * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
+ * resulting delta can be used with {@link #updateFrom(Configuration)}.
+ * <p />
+ * Caveat: If the any of the Configuration's members becomes undefined, then
+ * {@link #updateFrom(Configuration)} will treat it as a no-op and not update that member.
+ *
+ * This is fine for device configurations as no member is ever undefined.
+ * {@hide}
+ */
+ public static Configuration generateDelta(Configuration base, Configuration change) {
+ final Configuration delta = new Configuration();
+ if (base.fontScale != change.fontScale) {
+ delta.fontScale = change.fontScale;
+ }
+
+ if (base.mcc != change.mcc) {
+ delta.mcc = change.mcc;
+ }
+
+ if (base.mnc != change.mnc) {
+ delta.mnc = change.mnc;
+ }
+
+ if ((base.locale == null && change.locale != null) ||
+ (base.locale != null && !base.locale.equals(change.locale))) {
+ delta.locale = change.locale;
+ }
+
+ if (base.touchscreen != change.touchscreen) {
+ delta.touchscreen = change.touchscreen;
+ }
+
+ if (base.keyboard != change.keyboard) {
+ delta.keyboard = change.keyboard;
+ }
+
+ if (base.keyboardHidden != change.keyboardHidden) {
+ delta.keyboardHidden = change.keyboardHidden;
+ }
+
+ if (base.navigation != change.navigation) {
+ delta.navigation = change.navigation;
+ }
+
+ if (base.navigationHidden != change.navigationHidden) {
+ delta.navigationHidden = change.navigationHidden;
+ }
+
+ if (base.orientation != change.orientation) {
+ delta.orientation = change.orientation;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_SIZE_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_SIZE_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_SIZE_MASK;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
+ }
+
+ if ((base.screenLayout & SCREENLAYOUT_LONG_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_LONG_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
+ }
+
+ if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
+ delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
+ }
+
+ if ((base.uiMode & UI_MODE_NIGHT_MASK) != (change.uiMode & UI_MODE_NIGHT_MASK)) {
+ delta.uiMode |= change.uiMode & UI_MODE_NIGHT_MASK;
+ }
+
+ if (base.screenWidthDp != change.screenWidthDp) {
+ delta.screenWidthDp = change.screenWidthDp;
+ }
+
+ if (base.screenHeightDp != change.screenHeightDp) {
+ delta.screenHeightDp = change.screenHeightDp;
+ }
+
+ if (base.smallestScreenWidthDp != change.smallestScreenWidthDp) {
+ delta.smallestScreenWidthDp = change.smallestScreenWidthDp;
+ }
+
+ if (base.densityDpi != change.densityDpi) {
+ delta.densityDpi = change.densityDpi;
+ }
+ return delta;
+ }
+
+ private static final String XML_ATTR_FONT_SCALE = "fs";
+ private static final String XML_ATTR_MCC = "mcc";
+ private static final String XML_ATTR_MNC = "mnc";
+ private static final String XML_ATTR_LOCALE = "locale";
+ private static final String XML_ATTR_TOUCHSCREEN = "touch";
+ private static final String XML_ATTR_KEYBOARD = "key";
+ private static final String XML_ATTR_KEYBOARD_HIDDEN = "keyHid";
+ private static final String XML_ATTR_HARD_KEYBOARD_HIDDEN = "hardKeyHid";
+ private static final String XML_ATTR_NAVIGATION = "nav";
+ private static final String XML_ATTR_NAVIGATION_HIDDEN = "navHid";
+ private static final String XML_ATTR_ORIENTATION = "ori";
+ private static final String XML_ATTR_SCREEN_LAYOUT = "scrLay";
+ private static final String XML_ATTR_UI_MODE = "ui";
+ private static final String XML_ATTR_SCREEN_WIDTH = "width";
+ private static final String XML_ATTR_SCREEN_HEIGHT = "height";
+ private static final String XML_ATTR_SMALLEST_WIDTH = "sw";
+ private static final String XML_ATTR_DENSITY = "density";
+
+ /**
+ * Reads the attributes corresponding to Configuration member fields from the Xml parser.
+ * The parser is expected to be on a tag which has Configuration attributes.
+ *
+ * @param parser The Xml parser from which to read attributes.
+ * @param configOut The Configuration to populate from the Xml attributes.
+ * {@hide}
+ */
+ public static void readXmlAttrs(XmlPullParser parser, Configuration configOut)
+ throws XmlPullParserException, IOException {
+ configOut.fontScale = Float.intBitsToFloat(
+ XmlUtils.readIntAttribute(parser, XML_ATTR_FONT_SCALE, 0));
+ configOut.mcc = XmlUtils.readIntAttribute(parser, XML_ATTR_MCC, 0);
+ configOut.mnc = XmlUtils.readIntAttribute(parser, XML_ATTR_MNC, 0);
+
+ final String localeStr = XmlUtils.readStringAttribute(parser, XML_ATTR_LOCALE);
+ if (localeStr != null) {
+ configOut.locale = Locale.forLanguageTag(localeStr);
+ }
+
+ configOut.touchscreen = XmlUtils.readIntAttribute(parser, XML_ATTR_TOUCHSCREEN,
+ TOUCHSCREEN_UNDEFINED);
+ configOut.keyboard = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD,
+ KEYBOARD_UNDEFINED);
+ configOut.keyboardHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_KEYBOARD_HIDDEN,
+ KEYBOARDHIDDEN_UNDEFINED);
+ configOut.hardKeyboardHidden =
+ XmlUtils.readIntAttribute(parser, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+ HARDKEYBOARDHIDDEN_UNDEFINED);
+ configOut.navigation = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION,
+ NAVIGATION_UNDEFINED);
+ configOut.navigationHidden = XmlUtils.readIntAttribute(parser, XML_ATTR_NAVIGATION_HIDDEN,
+ NAVIGATIONHIDDEN_UNDEFINED);
+ configOut.orientation = XmlUtils.readIntAttribute(parser, XML_ATTR_ORIENTATION,
+ ORIENTATION_UNDEFINED);
+ configOut.screenLayout = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_LAYOUT,
+ SCREENLAYOUT_UNDEFINED);
+ configOut.uiMode = XmlUtils.readIntAttribute(parser, XML_ATTR_UI_MODE, 0);
+ configOut.screenWidthDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_WIDTH,
+ SCREEN_WIDTH_DP_UNDEFINED);
+ configOut.screenHeightDp = XmlUtils.readIntAttribute(parser, XML_ATTR_SCREEN_HEIGHT,
+ SCREEN_HEIGHT_DP_UNDEFINED);
+ configOut.smallestScreenWidthDp =
+ XmlUtils.readIntAttribute(parser, XML_ATTR_SMALLEST_WIDTH,
+ SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
+ configOut.densityDpi = XmlUtils.readIntAttribute(parser, XML_ATTR_DENSITY,
+ DENSITY_DPI_UNDEFINED);
+ }
+
+
+ /**
+ * Writes the Configuration's member fields as attributes into the XmlSerializer.
+ * The serializer is expected to have already started a tag so that attributes can be
+ * immediately written.
+ *
+ * @param xml The serializer to which to write the attributes.
+ * @param config The Configuration whose member fields to write.
+ * {@hide}
+ */
+ public static void writeXmlAttrs(XmlSerializer xml, Configuration config) throws IOException {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_FONT_SCALE,
+ Float.floatToIntBits(config.fontScale));
+ if (config.mcc != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_MCC, config.mcc);
+ }
+ if (config.mnc != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_MNC, config.mnc);
+ }
+ if (config.locale != null) {
+ XmlUtils.writeStringAttribute(xml, XML_ATTR_LOCALE, config.locale.toLanguageTag());
+ }
+ if (config.touchscreen != TOUCHSCREEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_TOUCHSCREEN, config.touchscreen);
+ }
+ if (config.keyboard != KEYBOARD_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD, config.keyboard);
+ }
+ if (config.keyboardHidden != KEYBOARDHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_KEYBOARD_HIDDEN, config.keyboardHidden);
+ }
+ if (config.hardKeyboardHidden != HARDKEYBOARDHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_HARD_KEYBOARD_HIDDEN,
+ config.hardKeyboardHidden);
+ }
+ if (config.navigation != NAVIGATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION, config.navigation);
+ }
+ if (config.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_NAVIGATION_HIDDEN, config.navigationHidden);
+ }
+ if (config.orientation != ORIENTATION_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_ORIENTATION, config.orientation);
+ }
+ if (config.screenLayout != SCREENLAYOUT_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_LAYOUT, config.screenLayout);
+ }
+ if (config.uiMode != 0) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_UI_MODE, config.uiMode);
+ }
+ if (config.screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_WIDTH, config.screenWidthDp);
+ }
+ if (config.screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SCREEN_HEIGHT, config.screenHeightDp);
+ }
+ if (config.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_SMALLEST_WIDTH, config.smallestScreenWidthDp);
+ }
+ if (config.densityDpi != DENSITY_DPI_UNDEFINED) {
+ XmlUtils.writeIntAttribute(xml, XML_ATTR_DENSITY, config.densityDpi);
+ }
+ }
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 31813c10..cabe228 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1572,6 +1572,16 @@
}
/**
+ * Gets all of the attribute ids associated with this {@link Theme}. For debugging only.
+ *
+ * @return The int array containing attribute ids associated with this {@link Theme}.
+ * @hide
+ */
+ public int[] getAllAttributes() {
+ return mAssets.getStyleAttributes(getAppliedStyleResId());
+ }
+
+ /**
* Returns the resources to which this theme belongs.
*
* @return Resources to which this theme belongs.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index b52a0c5..f514e42 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -737,12 +737,11 @@
}
/**
- * This value is defined only for continuous mode sensors. It is the delay between two
- * sensor events corresponding to the lowest frequency that this sensor supports. When
- * lower frequencies are requested through registerListener() the events will be generated
- * at this frequency instead. It can be used to estimate when the batch FIFO may be full.
- * Older devices may set this value to zero. Ignore this value in case it is negative
- * or zero.
+ * This value is defined only for continuous and on-change sensors. It is the delay between two
+ * sensor events corresponding to the lowest frequency that this sensor supports. When lower
+ * frequencies are requested through registerListener() the events will be generated at this
+ * frequency instead. It can be used to estimate when the batch FIFO may be full. Older devices
+ * may set this value to zero. Ignore this value in case it is negative or zero.
*
* @return The max delay for this sensor in microseconds.
*/
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index ca71e81..91ef6ca 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -61,7 +61,7 @@
*
* <p>The camera has failed to open or has failed at a later time
* as a result of some non-user interaction. Refer to
- * {@link CameraDevice.StateListener#onError} for the exact
+ * {@link CameraDevice.StateCallback#onError} for the exact
* nature of the error.</p>
*
* <p>No further calls to the camera will succeed. Clean up
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index fc2141f..ce83028 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -32,18 +32,18 @@
* sending images to the desired targets. Therefore the setup is done asynchronously, and
* {@link CameraDevice#createCaptureSession createCaptureSession} will send the ready-to-use
* CameraCaptureSession to the provided listener's
- * {@link CameraCaptureSession.StateListener#onConfigured onConfigured} callback. If configuration
+ * {@link CameraCaptureSession.StateCallback#onConfigured onConfigured} callback. If configuration
* cannot be completed, then the
- * {@link CameraCaptureSession.StateListener#onConfigureFailed onConfigureFailed} is called, and the
+ * {@link CameraCaptureSession.StateCallback#onConfigureFailed onConfigureFailed} is called, and the
* session will not become active.</p>
*<!--
* <p>Any capture requests (repeating or non-repeating) submitted before the session is ready will
* be queued up and will begin capture once the session becomes ready. In case the session cannot be
- * configured and {@link StateListener#onConfigureFailed onConfigureFailed} is called, all queued
+ * configured and {@link StateCallback#onConfigureFailed onConfigureFailed} is called, all queued
* capture requests are discarded.</p>
*-->
* <p>If a new session is created by the camera device, then the previous session is closed, and its
- * associated {@link StateListener#onClosed onClosed} callback will be invoked. All
+ * associated {@link StateCallback#onClosed onClosed} callback will be invoked. All
* of the session methods will throw an IllegalStateException if called once the session is
* closed.</p>
*
@@ -86,7 +86,7 @@
* looper}.
*
* @return int A unique capture sequence ID used by
- * {@link CaptureListener#onCaptureSequenceCompleted}.
+ * {@link CaptureCallback#onCaptureSequenceCompleted}.
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
@@ -103,7 +103,7 @@
* @see #setRepeatingBurst
* @see #abortCaptures
*/
- public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
+ public abstract int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
throws CameraAccessException;
/**
@@ -131,7 +131,7 @@
* looper}.
*
* @return int A unique capture sequence ID used by
- * {@link CaptureListener#onCaptureSequenceCompleted}.
+ * {@link CaptureCallback#onCaptureSequenceCompleted}.
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
@@ -147,7 +147,7 @@
* @see #setRepeatingBurst
* @see #abortCaptures
*/
- public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public abstract int captureBurst(List<CaptureRequest> requests, CaptureCallback listener,
Handler handler) throws CameraAccessException;
/**
@@ -185,7 +185,7 @@
* looper}.
*
* @return int A unique capture sequence ID used by
- * {@link CaptureListener#onCaptureSequenceCompleted}.
+ * {@link CaptureCallback#onCaptureSequenceCompleted}.
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
@@ -203,7 +203,7 @@
* @see #stopRepeating
* @see #abortCaptures
*/
- public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ public abstract int setRepeatingRequest(CaptureRequest request, CaptureCallback listener,
Handler handler) throws CameraAccessException;
/**
@@ -245,7 +245,7 @@
* looper}.
*
* @return int A unique capture sequence ID used by
- * {@link CaptureListener#onCaptureSequenceCompleted}.
+ * {@link CaptureCallback#onCaptureSequenceCompleted}.
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
@@ -263,7 +263,7 @@
* @see #stopRepeating
* @see #abortCaptures
*/
- public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback listener,
Handler handler) throws CameraAccessException;
/**
@@ -274,7 +274,7 @@
*
* <p>Any currently in-flight captures will still complete, as will any burst that is
* mid-capture. To ensure that the device has finished processing all of its capture requests
- * and is in ready state, wait for the {@link StateListener#onReady} callback after
+ * and is in ready state, wait for the {@link StateCallback#onReady} callback after
* calling this method.</p>
*
* @throws CameraAccessException if the camera device is no longer connected or has
@@ -285,7 +285,7 @@
*
* @see #setRepeatingRequest
* @see #setRepeatingBurst
- * @see StateListener#onIdle
+ * @see StateCallback#onIdle
*/
public abstract void stopRepeating() throws CameraAccessException;
@@ -293,15 +293,15 @@
* Discard all captures currently pending and in-progress as fast as possible.
*
* <p>The camera device will discard all of its current work as fast as possible. Some in-flight
- * captures may complete successfully and call {@link CaptureListener#onCaptureCompleted}, while
- * others will trigger their {@link CaptureListener#onCaptureFailed} callbacks. If a repeating
+ * captures may complete successfully and call {@link CaptureCallback#onCaptureCompleted}, while
+ * others will trigger their {@link CaptureCallback#onCaptureFailed} callbacks. If a repeating
* request or a repeating burst is set, it will be cleared.</p>
*
* <p>This method is the fastest way to switch the camera device to a new session with
* {@link CameraDevice#createCaptureSession}, at the cost of discarding in-progress work. It
* must be called before the new session is created. Once all pending requests are either
- * completed or thrown away, the {@link StateListener#onReady} callback will be called,
- * if the session has not been closed. Otherwise, the {@link StateListener#onClosed}
+ * completed or thrown away, the {@link StateCallback#onReady} callback will be called,
+ * if the session has not been closed. Otherwise, the {@link StateCallback#onClosed}
* callback will be fired when a new session is created by the camera device.</p>
*
* <p>Cancelling will introduce at least a brief pause in the stream of data from the camera
@@ -332,7 +332,7 @@
*
* <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession}
* will close any existing capture session automatically, and call the older session listener's
- * {@link StateListener#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
+ * {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession}
* directly without closing is the recommended approach for quickly switching to a new session,
* since unchanged target outputs can be reused more efficiently.</p>
*
@@ -340,7 +340,7 @@
* repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
* However, any in-progress capture requests submitted to the session will be completed as
* normal; once all captures have completed and the session has been torn down,
- * {@link StateListener#onClosed} will be called.</p>
+ * {@link StateCallback#onClosed} will be called.</p>
*
* <p>Closing a session is idempotent; closing more than once has no effect.</p>
*/
@@ -348,10 +348,10 @@
public abstract void close();
/**
- * A listener for tracking the state of a camera capture session.
+ * A callback object for receiving updates about the state of a camera capture session.
*
*/
- public static abstract class StateListener {
+ public static abstract class StateCallback {
/**
* This method is called when the camera device has finished configuring itself, and the
@@ -439,10 +439,17 @@
}
/**
- * <p>A listener for tracking the progress of a {@link CaptureRequest}
- * submitted to the camera device.</p>
+ * Temporary for migrating to Callback naming
+ * @hide
+ */
+ public static abstract class StateListener extends StateCallback {
+ }
+
+ /**
+ * <p>A callback object for tracking the progress of a {@link CaptureRequest} submitted to the
+ * camera device.</p>
*
- * <p>This listener is called when a request triggers a capture to start,
+ * <p>This callback is invoked when a request triggers a capture to start,
* and when the capture is complete. In case on an error capturing an image,
* the error method is triggered instead of the completion method.</p>
*
@@ -451,7 +458,7 @@
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public static abstract class CaptureListener {
+ public static abstract class CaptureCallback {
/**
* This constant is used to indicate that no images were captured for
@@ -476,7 +483,9 @@
* and in the buffers sent to each output Surface. These buffer
* timestamps are accessible through, for example,
* {@link android.media.Image#getTimestamp() Image.getTimestamp()} or
- * {@link android.graphics.SurfaceTexture#getTimestamp()}.</p>
+ * {@link android.graphics.SurfaceTexture#getTimestamp()}.
+ * The frame number included is equal to the frame number that will be included in
+ * {@link CaptureResult#getFrameNumber}.</p>
*
* <p>For the simplest way to play a shutter sound camera shutter or a
* video recording start/stop sound, see the
@@ -487,10 +496,21 @@
* @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request the request for the capture that just begun
* @param timestamp the timestamp at start of capture, in nanoseconds.
+ * @param frameNumber the frame number for this capture
*
* @see android.media.MediaActionSound
*/
public void onCaptureStarted(CameraCaptureSession session,
+ CaptureRequest request, long timestamp, long frameNumber) {
+ // Temporary trampoline for API change transition
+ onCaptureStarted(session, request, timestamp);
+ }
+
+ /**
+ * Temporary for API change transition
+ * @hide
+ */
+ public void onCaptureStarted(CameraCaptureSession session,
CaptureRequest request, long timestamp) {
// default empty implementation
}
@@ -625,7 +645,7 @@
}
/**
- * This method is called independently of the others in CaptureListener,
+ * This method is called independently of the others in CaptureCallback,
* when a capture sequence finishes and all {@link CaptureResult}
* or {@link CaptureFailure} for it have been returned via this listener.
*
@@ -655,7 +675,7 @@
}
/**
- * This method is called independently of the others in CaptureListener,
+ * This method is called independently of the others in CaptureCallback,
* when a capture sequence aborts before any {@link CaptureResult}
* or {@link CaptureFailure} for it have been returned via this listener.
*
@@ -684,4 +704,11 @@
}
}
+ /**
+ * Temporary for migrating to Callback naming
+ * @hide
+ */
+ public static abstract class CaptureListener extends CaptureCallback {
+ }
+
}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6a9d565..0bb742c 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -199,8 +199,8 @@
* <p>It can take several hundred milliseconds for the session's configuration to complete,
* since camera hardware may need to be powered on or reconfigured. Once the configuration is
* complete and the session is ready to actually capture data, the provided
- * {@link CameraCaptureSession.StateListener}'s
- * {@link CameraCaptureSession.StateListener#onConfigured} callback will be called.</p>
+ * {@link CameraCaptureSession.StateCallback}'s
+ * {@link CameraCaptureSession.StateCallback#onConfigured} callback will be called.</p>
*
* <p>If a prior CameraCaptureSession already exists when a new one is created, the previous
* session is closed. Any in-progress capture requests made on the prior session will be
@@ -216,14 +216,136 @@
* <p>Configuring a session with an empty or null list will close the current session, if
* any. This can be used to release the current session's target surfaces for another use.</p>
*
+ * <p>While any of the sizes from {@link StreamConfigurationMap#getOutputSizes} can be used when
+ * a single output stream is configured, a given camera device may not be able to support all
+ * combination of sizes, formats, and targets when multiple outputs are configured at once. The
+ * tables below list the maximum guaranteed resolutions for combinations of streams and targets,
+ * given the capabilities of the camera device.</p>
+ *
+ * <p>If an application tries to create a session using a set of targets that exceed the limits
+ * described in the below tables, one of three possibilities may occur. First, the session may
+ * be successfully created and work normally. Second, the session may be successfully created,
+ * but the camera device won't meet the frame rate guarantees as described in
+ * {@link StreamConfigurationMap#getOutputMinFrameDuration}. Or third, if the output set
+ * cannot be used at all, session creation will fail entirely, with
+ * {@link CameraCaptureSession.StateListener#onConfigureFailed} being invoked.</p>
+ *
+ * <p>For the type column, {@code PRIV} refers to any target whose available sizes are found
+ * using {@link StreamConfigurationMap#getOutputSizes(Class)} with no direct application-visible
+ * format, {@code YUV} refers to a target Surface using the
+ * {@link android.graphics.ImageFormat#YUV_420_888} format, {@code JPEG} refers to the
+ * {@link android.graphics.ImageFormat#JPEG} format, and {@code RAW} refers to the
+ * {@link android.graphics.ImageFormat#RAW_SENSOR} format.</p>
+ *
+ * <p>For the maximum size column, {@code PREVIEW} refers to the best size match to the
+ * device's screen resolution, or to 1080p ({@code 1920x1080}), whichever is
+ * smaller. {@code RECORD} refers to the camera device's maximum supported recording resolution,
+ * as determined by {@link android.media.CamcorderProfile}. And {@code MAXIMUM} refers to the
+ * camera device's maximum output resolution for that format or target from
+ * {@link StreamConfigurationMap#getOutputSizes}.</p>
+ *
+ * <p>To use these tables, determine the number and the formats/targets of outputs needed, and
+ * find the row(s) of the table with those targets. The sizes indicate the maximum set of sizes
+ * that can be used; it is guaranteed that for those targets, the listed sizes and anything
+ * smaller from the list given by {@link StreamConfigurationMap#getOutputSizes} can be
+ * successfully used to create a session. For example, if a row indicates that a 8 megapixel
+ * (MP) YUV_420_888 output can be used together with a 2 MP {@code PRIV} output, then a session
+ * can be created with targets {@code [8 MP YUV, 2 MP PRIV]} or targets {@code [2 MP YUV, 2 MP
+ * PRIV]}; but a session with targets {@code [8 MP YUV, 4 MP PRIV]}, targets {@code [4 MP YUV, 4
+ * MP PRIV]}, or targets {@code [8 MP PRIV, 2 MP YUV]} would not be guaranteed to work, unless
+ * some other row of the table lists such a combination.</p>
+ *
+ * <style scoped>
+ * #rb { border-right-width: thick; }
+ * </style>
+ * <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
+ * least the following stream combinations:
+ *
+ * <table>
+ * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
+ * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-viewfinder still image capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus still capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Standard recording.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Preview plus in-app processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture plus in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Limited-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution in-app video processing with preview.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>Two-input in-app video processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution in-app processing with video snapshot.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing with still capture.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>FULL-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">FULL-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with maximum-size video snapshot</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard video recording plus maximum-resolution in-app processing.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview plus two-input maximum-resolution in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+ * at least the following stream combinations on both
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard DNG capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview with in-app processing and DNG capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture with simultaneous JPEG and DNG.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app processing with simultaneous JPEG and DNG.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Since the capabilities of camera devices vary greatly, a given camera device may support
+ * target combinations with sizes outside of these guarantees, but this can only be tested for
+ * by attempting to create a session with such targets.</p>
+ *
* @param outputs The new set of Surfaces that should be made available as
* targets for captured image data.
- * @param listener The listener to notify about the status of the new capture session.
- * @param handler The handler on which the listener should be invoked, or {@code null} to use
+ * @param callback The callback to notify about the status of the new capture session.
+ * @param handler The handler on which the callback should be invoked, or {@code null} to use
* the current thread's {@link android.os.Looper looper}.
*
* @throws IllegalArgumentException if the set of output Surfaces do not meet the requirements,
- * the listener is null, or the handler is null but the current
+ * the callback is null, or the handler is null but the current
* thread has no looper.
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
@@ -235,7 +357,7 @@
* @see StreamConfigurationMap#getOutputSizes(Class)
*/
public abstract void createCaptureSession(List<Surface> outputs,
- CameraCaptureSession.StateListener listener, Handler handler)
+ CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException;
/**
@@ -271,10 +393,10 @@
*
* <p>Immediately after this call, all calls to the camera device or active session interface
* will throw a {@link IllegalStateException}, except for calls to close(). Once the device has
- * fully shut down, the {@link StateListener#onClosed} callback will be called, and the camera
+ * fully shut down, the {@link StateCallback#onClosed} callback will be called, and the camera
* is free to be re-opened.</p>
*
- * <p>Immediately after this call, besides the final {@link StateListener#onClosed} calls, no
+ * <p>Immediately after this call, besides the final {@link StateCallback#onClosed} calls, no
* further callbacks from the device or the active session will occur, and any remaining
* submitted capture requests will be discarded, as if
* {@link CameraCaptureSession#abortCaptures} had been called, except that no success or failure
@@ -285,24 +407,24 @@
public abstract void close();
/**
- * A listener for notifications about the state of a camera
- * device.
+ * A callback objects for receiving updates about the state of a camera device.
*
- * <p>A listener must be provided to the {@link CameraManager#openCamera}
- * method to open a camera device.</p>
+ * <p>A callback instance must be provided to the {@link CameraManager#openCamera} method to
+ * open a camera device.</p>
*
- * <p>These events include notifications about the device completing startup (
+ * <p>These state updates include notifications about the device completing startup (
* allowing for {@link #createCaptureSession} to be called), about device
* disconnection or closure, and about unexpected device errors.</p>
*
* <p>Events about the progress of specific {@link CaptureRequest CaptureRequests} are provided
- * through a {@link CameraCaptureSession.CaptureListener} given to the
+ * through a {@link CameraCaptureSession.CaptureCallback} given to the
* {@link CameraCaptureSession#capture}, {@link CameraCaptureSession#captureBurst},
- * {@link CameraCaptureSession#setRepeatingRequest}, or {@link CameraCaptureSession#setRepeatingBurst} methods.
+ * {@link CameraCaptureSession#setRepeatingRequest}, or
+ * {@link CameraCaptureSession#setRepeatingBurst} methods.
*
* @see CameraManager#openCamera
*/
- public static abstract class StateListener {
+ public static abstract class StateCallback {
/**
* An error code that can be reported by {@link #onError}
* indicating that the camera device is in use already.
@@ -408,7 +530,7 @@
* of a removable camera device; or the camera being needed for a
* higher-priority use case.</p>
*
- * <p>There may still be capture listener callbacks that are called
+ * <p>There may still be capture callbacks that are invoked
* after this method is called, or new image buffers that are delivered
* to active outputs.</p>
*
@@ -417,7 +539,7 @@
*
* <p>You should clean up the camera with {@link CameraDevice#close} after
* this happens, as it is not recoverable until opening the camera again
- * after it becomes {@link CameraManager.AvailabilityListener#onCameraAvailable available}.
+ * after it becomes {@link CameraManager.AvailabilityCallback#onCameraAvailable available}.
* </p>
*
* @param camera the device that has been disconnected
@@ -436,7 +558,7 @@
* {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
* </p>
*
- * <p>There may still be capture completion or camera stream listeners
+ * <p>There may still be capture completion or camera stream callbacks
* that will be called after this error is received.</p>
*
* <p>You should clean up the camera with {@link CameraDevice#close} after
@@ -444,7 +566,7 @@
*
* @param camera The device reporting the error
* @param error The error code, one of the
- * {@code StateListener.ERROR_*} values.
+ * {@code StateCallback.ERROR_*} values.
*
* @see #ERROR_CAMERA_DEVICE
* @see #ERROR_CAMERA_SERVICE
@@ -455,6 +577,13 @@
}
/**
+ * Temporary for migrating to Callback naming
+ * @hide
+ */
+ public static abstract class StateListener extends StateCallback {
+ }
+
+ /**
* To be inherited by android.hardware.camera2.* code only.
* @hide
*/
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index a4a1559..9a9e4c2 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -69,8 +69,8 @@
private ArrayList<String> mDeviceIdList;
- private final ArrayMap<AvailabilityListener, Handler> mListenerMap =
- new ArrayMap<AvailabilityListener, Handler>();
+ private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
+ new ArrayMap<AvailabilityCallback, Handler>();
private final Context mContext;
private final Object mLock = new Object();
@@ -108,19 +108,19 @@
}
/**
- * Register a listener to be notified about camera device availability.
+ * Register a callback to be notified about camera device availability.
*
- * <p>Registering the same listener again will replace the handler with the
+ * <p>Registering the same callback again will replace the handler with the
* new one provided.</p>
*
- * <p>The first time a listener is registered, it is immediately called
+ * <p>The first time a callback is registered, it is immediately called
* with the availability status of all currently known camera devices.</p>
*
- * @param listener The new listener to send camera availability notices to
- * @param handler The handler on which the listener should be invoked, or
+ * @param callback the new callback to send camera availability notices to
+ * @param handler The handler on which the callback should be invoked, or
* {@code null} to use the current thread's {@link android.os.Looper looper}.
*/
- public void addAvailabilityListener(AvailabilityListener listener, Handler handler) {
+ public void registerAvailabilityCallback(AvailabilityCallback callback, Handler handler) {
if (handler == null) {
Looper looper = Looper.myLooper();
if (looper == null) {
@@ -131,25 +131,25 @@
}
synchronized (mLock) {
- Handler oldHandler = mListenerMap.put(listener, handler);
- // For new listeners, provide initial availability information
+ Handler oldHandler = mCallbackMap.put(callback, handler);
+ // For new callbacks, provide initial availability information
if (oldHandler == null) {
- mServiceListener.updateListenerLocked(listener, handler);
+ mServiceListener.updateCallbackLocked(callback, handler);
}
}
}
/**
- * Remove a previously-added listener; the listener will no longer receive
- * connection and disconnection callbacks.
+ * Remove a previously-added callback; the callback will no longer receive connection and
+ * disconnection callbacks.
*
- * <p>Removing a listener that isn't registered has no effect.</p>
+ * <p>Removing a callback that isn't registered has no effect.</p>
*
- * @param listener The listener to remove from the notification list
+ * @param callback The callback to remove from the notification list
*/
- public void removeAvailabilityListener(AvailabilityListener listener) {
+ public void unregisterAvailabilityCallback(AvailabilityCallback callback) {
synchronized (mLock) {
- mListenerMap.remove(listener);
+ mCallbackMap.remove(callback);
}
}
@@ -228,8 +228,8 @@
* Helper for openning a connection to a camera with the given ID.
*
* @param cameraId The unique identifier of the camera device to open
- * @param listener The listener for the camera. Must not be null.
- * @param handler The handler to call the listener on. Must not be null.
+ * @param callback The callback for the camera. Must not be null.
+ * @param handler The handler to invoke the callback on. Must not be null.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* or too many camera devices are already open, or the cameraId does not match
@@ -237,14 +237,14 @@
*
* @throws SecurityException if the application does not have permission to
* access the camera
- * @throws IllegalArgumentException if listener or handler is null.
+ * @throws IllegalArgumentException if callback or handler is null.
* @return A handle to the newly-created camera device.
*
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
private CameraDevice openCameraDeviceUserAsync(String cameraId,
- CameraDevice.StateListener listener, Handler handler)
+ CameraDevice.StateCallback callback, Handler handler)
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
@@ -257,7 +257,7 @@
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
- listener,
+ callback,
handler,
characteristics);
@@ -313,7 +313,7 @@
throw ce.asChecked();
}
- // TODO: factor out listener to be non-nested, then move setter to constructor
+ // TODO: factor out callback to be non-nested, then move setter to constructor
// For now, calling setRemoteDevice will fire initial
// onOpened/onUnconfigured callbacks.
deviceImpl.setRemoteDevice(cameraUser);
@@ -337,7 +337,7 @@
* is disconnected between the calls to {@link #getCameraIdList} and
* {@link #openCamera}.</p>
*
- * <p>Once the camera is successfully opened, {@link CameraDevice.StateListener#onOpened} will
+ * <p>Once the camera is successfully opened, {@link CameraDevice.StateCallback#onOpened} will
* be invoked with the newly opened {@link CameraDevice}. The camera device can then be set up
* for operation by calling {@link CameraDevice#createCaptureSession} and
* {@link CameraDevice#createCaptureRequest}</p>
@@ -345,31 +345,31 @@
* <!--
* <p>Since the camera device will be opened asynchronously, any asynchronous operations done
* on the returned CameraDevice instance will be queued up until the device startup has
- * completed and the listener's {@link CameraDevice.StateListener#onOpened onOpened} method is
+ * completed and the callback's {@link CameraDevice.StateCallback#onOpened onOpened} method is
* called. The pending operations are then processed in order.</p>
* -->
* <p>If the camera becomes disconnected during initialization
* after this function call returns,
- * {@link CameraDevice.StateListener#onDisconnected} with a
+ * {@link CameraDevice.StateCallback#onDisconnected} with a
* {@link CameraDevice} in the disconnected state (and
- * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
+ * {@link CameraDevice.StateCallback#onOpened} will be skipped).</p>
*
- * <p>If opening the camera device fails, then the device listener's
- * {@link CameraDevice.StateListener#onError onError} method will be called, and subsequent
+ * <p>If opening the camera device fails, then the device callback's
+ * {@link CameraDevice.StateCallback#onError onError} method will be called, and subsequent
* calls on the camera device will throw a {@link CameraAccessException}.</p>
*
* @param cameraId
* The unique identifier of the camera device to open
- * @param listener
- * The listener which is invoked once the camera is opened
+ * @param callback
+ * The callback which is invoked once the camera is opened
* @param handler
- * The handler on which the listener should be invoked, or
+ * The handler on which the callback should be invoked, or
* {@code null} to use the current thread's {@link android.os.Looper looper}.
*
* @throws CameraAccessException if the camera is disabled by device policy,
* or the camera has become or was disconnected.
*
- * @throws IllegalArgumentException if cameraId or the listener was null,
+ * @throws IllegalArgumentException if cameraId or the callback was null,
* or the cameraId does not match any currently or previously available
* camera device.
*
@@ -379,14 +379,14 @@
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
- public void openCamera(String cameraId, final CameraDevice.StateListener listener,
+ public void openCamera(String cameraId, final CameraDevice.StateCallback callback,
Handler handler)
throws CameraAccessException {
if (cameraId == null) {
throw new IllegalArgumentException("cameraId was null");
- } else if (listener == null) {
- throw new IllegalArgumentException("listener was null");
+ } else if (callback == null) {
+ throw new IllegalArgumentException("callback was null");
} else if (handler == null) {
if (Looper.myLooper() != null) {
handler = new Handler();
@@ -396,11 +396,11 @@
}
}
- openCameraDeviceUserAsync(cameraId, listener, handler);
+ openCameraDeviceUserAsync(cameraId, callback, handler);
}
/**
- * A listener for camera devices becoming available or
+ * A callback for camera devices becoming available or
* unavailable to open.
*
* <p>Cameras become available when they are no longer in use, or when a new
@@ -408,13 +408,13 @@
* application or service starts using a camera, or when a removable camera
* is disconnected.</p>
*
- * <p>Extend this listener and pass an instance of the subclass to
- * {@link CameraManager#addAvailabilityListener} to be notified of such availability
+ * <p>Extend this callback and pass an instance of the subclass to
+ * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability
* changes.</p>
*
- * @see addAvailabilityListener
+ * @see registerAvailabilityCallback
*/
- public static abstract class AvailabilityListener {
+ public static abstract class AvailabilityCallback {
/**
* A new camera has become available to use.
@@ -432,7 +432,7 @@
*
* <p>If an application had an active CameraDevice instance for the
* now-disconnected camera, that application will receive a
- * {@link CameraDevice.StateListener#onDisconnected disconnection error}.</p>
+ * {@link CameraDevice.StateCallback#onDisconnected disconnection error}.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
@@ -444,6 +444,13 @@
}
/**
+ * Temporary for migrating to Callback naming
+ * @hide
+ */
+ public static abstract class AvailabilityListener extends AvailabilityCallback {
+ }
+
+ /**
* Return or create the list of currently connected camera devices.
*
* <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -707,14 +714,14 @@
}
}
- private void postSingleUpdate(final AvailabilityListener listener, final Handler handler,
+ private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler,
final String id, final int status) {
if (isAvailable(status)) {
handler.post(
new Runnable() {
@Override
public void run() {
- listener.onCameraAvailable(id);
+ callback.onCameraAvailable(id);
}
});
} else {
@@ -722,7 +729,7 @@
new Runnable() {
@Override
public void run() {
- listener.onCameraUnavailable(id);
+ callback.onCameraUnavailable(id);
}
});
}
@@ -732,11 +739,11 @@
* Send the state of all known cameras to the provided listener, to initialize
* the listener's knowledge of camera state.
*/
- public void updateListenerLocked(AvailabilityListener listener, Handler handler) {
+ public void updateCallbackLocked(AvailabilityCallback callback, Handler handler) {
for (int i = 0; i < mDeviceStatus.size(); i++) {
String id = mDeviceStatus.keyAt(i);
Integer status = mDeviceStatus.valueAt(i);
- postSingleUpdate(listener, handler, id, status);
+ postSingleUpdate(callback, handler, id, status);
}
}
@@ -795,12 +802,12 @@
return;
}
- final int listenerCount = mListenerMap.size();
- for (int i = 0; i < listenerCount; i++) {
- Handler handler = mListenerMap.valueAt(i);
- final AvailabilityListener listener = mListenerMap.keyAt(i);
+ final int callbackCount = mCallbackMap.size();
+ for (int i = 0; i < callbackCount; i++) {
+ Handler handler = mCallbackMap.valueAt(i);
+ final AvailabilityCallback callback = mCallbackMap.keyAt(i);
- postSingleUpdate(listener, handler, id, status);
+ postSingleUpdate(callback, handler, id, status);
}
} // onStatusChangedLocked
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
index b6d3b08..c168ff1 100644
--- a/core/java/android/hardware/camera2/CaptureFailure.java
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -65,12 +65,12 @@
* Get the request associated with this failed capture.
*
* <p>Whenever a request is unsuccessfully captured, with
- * {@link CameraCaptureSession.CaptureListener#onCaptureFailed},
+ * {@link CameraCaptureSession.CaptureCallback#onCaptureFailed},
* the {@code failed capture}'s {@code getRequest()} will return that {@code request}.
* </p>
*
* <p>In particular,
- * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+ * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() {
* {@literal @}Override
* void onCaptureFailed(CaptureRequest myRequest, CaptureFailure myFailure) {
* assert(myFailure.getRequest.equals(myRequest) == true);
@@ -135,7 +135,7 @@
*
* @return int The ID for the sequence of requests that this capture failure is the result of
*
- * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
+ * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted
*/
public int getSequenceId() {
return mSequenceId;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index bcdcd62..93eb3de 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -245,7 +245,7 @@
* <p>This tag is not used for anything by the camera device, but can be
* used by an application to easily identify a CaptureRequest when it is
* returned by
- * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted}
+ * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted}
* </p>
*
* @return the last tag Object set on this request, or {@code null} if
@@ -435,7 +435,7 @@
* <p>This tag is not used for anything by the camera device, but can be
* used by an application to easily identify a CaptureRequest when it is
* returned by
- * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted CaptureListener.onCaptureCompleted}
+ * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted CaptureCallback.onCaptureCompleted}
*
* @param tag an arbitrary Object to store with this request
* @see CaptureRequest#getTag
@@ -731,6 +731,8 @@
/**
* <p>List of areas to use for
* metering.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -746,7 +748,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -820,6 +824,8 @@
/**
* <p>List of areas to use for focus
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -835,7 +841,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -921,6 +929,8 @@
/**
* <p>List of areas to use for illuminant
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -936,7 +946,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f9c4df4..01276a2 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -268,13 +268,13 @@
* Get the request associated with this result.
*
* <p>Whenever a request has been fully or partially captured, with
- * {@link CameraCaptureSession.CaptureListener#onCaptureCompleted} or
- * {@link CameraCaptureSession.CaptureListener#onCaptureProgressed}, the {@code result}'s
+ * {@link CameraCaptureSession.CaptureCallback#onCaptureCompleted} or
+ * {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed}, the {@code result}'s
* {@code getRequest()} will return that {@code request}.
* </p>
*
* <p>For example,
- * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+ * <code><pre>cameraDevice.capture(someRequest, new CaptureCallback() {
* {@literal @}Override
* void onCaptureCompleted(CaptureRequest myRequest, CaptureResult myResult) {
* assert(myResult.getRequest.equals(myRequest) == true);
@@ -314,8 +314,8 @@
*
* @return int The ID for the sequence of requests that this capture result is a part of
*
- * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
- * @see CameraDevice.CaptureListener#onCaptureSequenceAborted
+ * @see CameraDevice.CaptureCallback#onCaptureSequenceCompleted
+ * @see CameraDevice.CaptureCallback#onCaptureSequenceAborted
*/
public int getSequenceId() {
return mSequenceId;
@@ -582,6 +582,8 @@
/**
* <p>List of areas to use for
* metering.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AE android.control.maxRegionsAe} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -597,7 +599,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AE
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -870,6 +874,8 @@
/**
* <p>List of areas to use for focus
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AF android.control.maxRegionsAf} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -885,7 +891,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AF
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@@ -1369,6 +1377,8 @@
/**
* <p>List of areas to use for illuminant
* estimation.</p>
+ * <p>Optional. Not available if {@link CameraCharacteristics#CONTROL_MAX_REGIONS_AWB android.control.maxRegionsAwb} is 0.
+ * Otherwise will always be present.</p>
* <p>The coordinate system is based on the active pixel array,
* with (0,0) being the top-left pixel in the active pixel array, and
* ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.width - 1,
@@ -1384,7 +1394,9 @@
* outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
* the camera device will ignore the sections outside the region and output the
* used sections in the result metadata.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
+ * @see CameraCharacteristics#CONTROL_MAX_REGIONS_AWB
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
diff --git a/core/java/android/hardware/camera2/TotalCaptureResult.java b/core/java/android/hardware/camera2/TotalCaptureResult.java
index 0895fe3..6f7dd78 100644
--- a/core/java/android/hardware/camera2/TotalCaptureResult.java
+++ b/core/java/android/hardware/camera2/TotalCaptureResult.java
@@ -45,7 +45,7 @@
*
* <p>{@link TotalCaptureResult} objects are immutable.</p>
*
- * @see CameraDevice.CaptureListener#onCaptureCompleted
+ * @see CameraDevice.CaptureCallback#onCaptureCompleted
*/
public final class TotalCaptureResult extends CaptureResult {
@@ -88,7 +88,7 @@
*
* <p>The list size will be inclusive between {@code 0} and
* {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}, with elements in ascending order
- * of when {@link CameraCaptureSession.CaptureListener#onCaptureProgressed} was invoked.</p>
+ * of when {@link CameraCaptureSession.CaptureCallback#onCaptureProgressed} was invoked.</p>
*
* @return unmodifiable list of partial results
*/
diff --git a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
index 02c3d87..c66a3a4 100644
--- a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
+++ b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
@@ -48,7 +48,8 @@
/**
* Invoke a method by its name.
*
- * <p>If more than one method exists in {@code targetClass}, the first method will be used.</p>
+ * <p>If more than one method exists in {@code targetClass}, the first method with the right
+ * number of arguments will be used, and later calls will all use that method.</p>
*
* @param methodName
* The name of the method, which will be matched 1:1 to the destination method
@@ -68,8 +69,9 @@
Method targetMethod = mMethods.get(methodName);
if (targetMethod == null) {
for (Method method : mTargetClass.getMethods()) {
- // TODO future: match by # of params and types of params if possible
- if (method.getName().equals(methodName)) {
+ // TODO future: match types of params if possible
+ if (method.getName().equals(methodName) &&
+ (params.length == method.getParameterTypes().length) ) {
targetMethod = method;
mMethods.put(methodName, targetMethod);
break;
diff --git a/core/java/android/hardware/camera2/impl/ListenerProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java
similarity index 83%
rename from core/java/android/hardware/camera2/impl/ListenerProxies.java
rename to core/java/android/hardware/camera2/impl/CallbackProxies.java
index f44f9ad..f0217ac 100644
--- a/core/java/android/hardware/camera2/impl/ListenerProxies.java
+++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java
@@ -27,22 +27,22 @@
import static com.android.internal.util.Preconditions.*;
/**
- * Proxy out invocations to the camera2 API listeners into a {@link Dispatchable}.
+ * Proxy out invocations to the camera2 API callbacks into a {@link Dispatchable}.
*
* <p>Since abstract classes do not support Java's dynamic {@code Proxy}, we have to
* to use our own proxy mechanism.</p>
*/
-public class ListenerProxies {
+public class CallbackProxies {
// TODO: replace with codegen
- public static class DeviceStateListenerProxy extends CameraDeviceImpl.StateListenerKK {
- private final MethodNameInvoker<CameraDeviceImpl.StateListenerKK> mProxy;
+ public static class DeviceStateCallbackProxy extends CameraDeviceImpl.StateCallbackKK {
+ private final MethodNameInvoker<CameraDeviceImpl.StateCallbackKK> mProxy;
- public DeviceStateListenerProxy(
- Dispatchable<CameraDeviceImpl.StateListenerKK> dispatchTarget) {
+ public DeviceStateCallbackProxy(
+ Dispatchable<CameraDeviceImpl.StateCallbackKK> dispatchTarget) {
dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
- mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateListenerKK.class);
+ mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.StateCallbackKK.class);
}
@Override
@@ -87,19 +87,19 @@
}
@SuppressWarnings("deprecation")
- public static class DeviceCaptureListenerProxy extends CameraDeviceImpl.CaptureListener {
- private final MethodNameInvoker<CameraDeviceImpl.CaptureListener> mProxy;
+ public static class DeviceCaptureCallbackProxy extends CameraDeviceImpl.CaptureCallback {
+ private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy;
- public DeviceCaptureListenerProxy(
- Dispatchable<CameraDeviceImpl.CaptureListener> dispatchTarget) {
+ public DeviceCaptureCallbackProxy(
+ Dispatchable<CameraDeviceImpl.CaptureCallback> dispatchTarget) {
dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
- mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureListener.class);
+ mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDeviceImpl.CaptureCallback.class);
}
@Override
public void onCaptureStarted(CameraDevice camera,
- CaptureRequest request, long timestamp) {
- mProxy.invoke("onCaptureStarted", camera, request, timestamp);
+ CaptureRequest request, long timestamp, long frameNumber) {
+ mProxy.invoke("onCaptureStarted", camera, request, timestamp, frameNumber);
}
@Override
@@ -139,15 +139,15 @@
}
}
- public static class SessionStateListenerProxy
- extends CameraCaptureSession.StateListener {
- private final MethodNameInvoker<CameraCaptureSession.StateListener> mProxy;
+ public static class SessionStateCallbackProxy
+ extends CameraCaptureSession.StateCallback {
+ private final MethodNameInvoker<CameraCaptureSession.StateCallback> mProxy;
- public SessionStateListenerProxy(
- Dispatchable<CameraCaptureSession.StateListener> dispatchTarget) {
+ public SessionStateCallbackProxy(
+ Dispatchable<CameraCaptureSession.StateCallback> dispatchTarget) {
dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
mProxy = new MethodNameInvoker<>(dispatchTarget,
- CameraCaptureSession.StateListener.class);
+ CameraCaptureSession.StateCallback.class);
}
@Override
@@ -177,7 +177,7 @@
}
}
- private ListenerProxies() {
+ private CallbackProxies() {
throw new AssertionError();
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 9ca1fba..843f117 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -45,11 +45,11 @@
/** User-specified set of surfaces used as the configuration outputs */
private final List<Surface> mOutputs;
/**
- * User-specified state listener, used for outgoing events; calls to this object will be
+ * User-specified state callback, used for outgoing events; calls to this object will be
* automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}.
*/
- private final CameraCaptureSession.StateListener mStateListener;
- /** User-specified state handler used for outgoing state listener events */
+ private final CameraCaptureSession.StateCallback mStateCallback;
+ /** User-specified state handler used for outgoing state callback events */
private final Handler mStateHandler;
/** Internal camera device; used to translate calls into existing deprecated API */
@@ -84,28 +84,28 @@
* (e.g. no pending captures, no repeating requests, no flush).</p>
*/
CameraCaptureSessionImpl(List<Surface> outputs,
- CameraCaptureSession.StateListener listener, Handler stateHandler,
+ CameraCaptureSession.StateCallback callback, Handler stateHandler,
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
Handler deviceStateHandler, boolean configureSuccess) {
if (outputs == null || outputs.isEmpty()) {
throw new IllegalArgumentException("outputs must be a non-null, non-empty list");
- } else if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
+ } else if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
}
// TODO: extra verification of outputs
mOutputs = outputs;
mStateHandler = checkHandler(stateHandler);
- mStateListener = createUserStateListenerProxy(mStateHandler, listener);
+ mStateCallback = createUserStateCallbackProxy(mStateHandler, callback);
mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null");
mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null");
/*
- * Use the same handler as the device's StateListener for all the internal coming events
+ * Use the same handler as the device's StateCallback for all the internal coming events
*
- * This ensures total ordering between CameraDevice.StateListener and
- * CameraDeviceImpl.CaptureListener events.
+ * This ensures total ordering between CameraDevice.StateCallback and
+ * CameraDeviceImpl.CaptureCallback events.
*/
mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(),
/*name*/"seq");
@@ -119,11 +119,11 @@
// CameraDevice should call configureOutputs and have it finish before constructing us
if (configureSuccess) {
- mStateListener.onConfigured(this);
+ mStateCallback.onConfigured(this);
if (VERBOSE) Log.v(TAG, "ctor - Created session successfully");
mConfigureSuccess = true;
} else {
- mStateListener.onConfigureFailed(this);
+ mStateCallback.onConfigureFailed(this);
mClosed = true; // do not fire any other callbacks, do not allow any other work
Log.e(TAG, "Failed to create capture session; configuration failed");
mConfigureSuccess = false;
@@ -136,7 +136,7 @@
}
@Override
- public synchronized int capture(CaptureRequest request, CaptureListener listener,
+ public synchronized int capture(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (request == null) {
throw new IllegalArgumentException("request must not be null");
@@ -145,19 +145,19 @@
checkNotClosed();
checkLegalToCapture();
- handler = checkHandler(handler, listener);
+ handler = checkHandler(handler, callback);
if (VERBOSE) {
- Log.v(TAG, "capture - request " + request + ", listener " + listener + " handler" +
+ Log.v(TAG, "capture - request " + request + ", callback " + callback + " handler" +
" " + handler);
}
return addPendingSequence(mDeviceImpl.capture(request,
- createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
}
@Override
- public synchronized int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public synchronized int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (requests == null) {
throw new IllegalArgumentException("requests must not be null");
@@ -168,20 +168,20 @@
checkNotClosed();
checkLegalToCapture();
- handler = checkHandler(handler, listener);
+ handler = checkHandler(handler, callback);
if (VERBOSE) {
CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
- Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", listener " +
- listener + " handler" + "" + handler);
+ Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", callback " +
+ callback + " handler" + "" + handler);
}
return addPendingSequence(mDeviceImpl.captureBurst(requests,
- createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
}
@Override
- public synchronized int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ public synchronized int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (request == null) {
throw new IllegalArgumentException("request must not be null");
@@ -190,20 +190,20 @@
checkNotClosed();
checkLegalToCapture();
- handler = checkHandler(handler, listener);
+ handler = checkHandler(handler, callback);
if (VERBOSE) {
- Log.v(TAG, "setRepeatingRequest - request " + request + ", listener " + listener +
+ Log.v(TAG, "setRepeatingRequest - request " + request + ", callback " + callback +
" handler" + " " + handler);
}
return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
- createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
}
@Override
public synchronized int setRepeatingBurst(List<CaptureRequest> requests,
- CaptureListener listener, Handler handler) throws CameraAccessException {
+ CaptureCallback callback, Handler handler) throws CameraAccessException {
if (requests == null) {
throw new IllegalArgumentException("requests must not be null");
} else if (requests.isEmpty()) {
@@ -213,16 +213,16 @@
checkNotClosed();
checkLegalToCapture();
- handler = checkHandler(handler, listener);
+ handler = checkHandler(handler, callback);
if (VERBOSE) {
CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
Log.v(TAG, "setRepeatingBurst - requests " + Arrays.toString(requestArray) +
- ", listener " + listener + " handler" + "" + handler);
+ ", callback " + callback + " handler" + "" + handler);
}
return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
- createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ createCaptureCallbackProxy(handler, callback), mDeviceHandler));
}
@Override
@@ -331,8 +331,8 @@
// or just suppress the ISE only and rely onClosed.
// Also skip any of the draining work if this is already closed.
- // Short-circuit; queue listener immediately and return
- mStateListener.onClosed(this);
+ // Short-circuit; queue callback immediately and return
+ mStateCallback.onClosed(this);
return;
} catch (CameraAccessException e) {
// OK: close does not throw checked exceptions.
@@ -360,30 +360,30 @@
}
/**
- * Post calls into a CameraCaptureSession.StateListener to the user-specified {@code handler}.
+ * Post calls into a CameraCaptureSession.StateCallback to the user-specified {@code handler}.
*/
- private StateListener createUserStateListenerProxy(Handler handler, StateListener listener) {
- InvokeDispatcher<StateListener> userListenerSink = new InvokeDispatcher<>(listener);
- HandlerDispatcher<StateListener> handlerPassthrough =
- new HandlerDispatcher<>(userListenerSink, handler);
+ private StateCallback createUserStateCallbackProxy(Handler handler, StateCallback callback) {
+ InvokeDispatcher<StateCallback> userCallbackSink = new InvokeDispatcher<>(callback);
+ HandlerDispatcher<StateCallback> handlerPassthrough =
+ new HandlerDispatcher<>(userCallbackSink, handler);
- return new ListenerProxies.SessionStateListenerProxy(handlerPassthrough);
+ return new CallbackProxies.SessionStateCallbackProxy(handlerPassthrough);
}
/**
* Forward callbacks from
- * CameraDeviceImpl.CaptureListener to the CameraCaptureSession.CaptureListener.
+ * CameraDeviceImpl.CaptureCallback to the CameraCaptureSession.CaptureCallback.
*
* <p>In particular, all calls are automatically split to go both to our own
- * internal listener, and to the user-specified listener (by transparently posting
+ * internal callback, and to the user-specified callback (by transparently posting
* to the user-specified handler).</p>
*
* <p>When a capture sequence finishes, update the pending checked sequences set.</p>
*/
@SuppressWarnings("deprecation")
- private CameraDeviceImpl.CaptureListener createCaptureListenerProxy(
- Handler handler, CaptureListener listener) {
- CameraDeviceImpl.CaptureListener localListener = new CameraDeviceImpl.CaptureListener() {
+ private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
+ Handler handler, CaptureCallback callback) {
+ CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() {
@Override
public void onCaptureSequenceCompleted(CameraDevice camera,
int sequenceId, long frameNumber) {
@@ -398,43 +398,43 @@
};
/*
- * Split the calls from the device listener into local listener and the following chain:
+ * Split the calls from the device callback into local callback and the following chain:
* - replace the first CameraDevice arg with a CameraCaptureSession
- * - duck type from device listener to session listener
+ * - duck type from device callback to session callback
* - then forward the call to a handler
- * - then finally invoke the destination method on the session listener object
+ * - then finally invoke the destination method on the session callback object
*/
- if (listener == null) {
- // OK: API allows the user to not specify a listener, and the handler may
+ if (callback == null) {
+ // OK: API allows the user to not specify a callback, and the handler may
// also be null in that case. Collapse whole dispatch chain to only call the local
- // listener
- return localListener;
+ // callback
+ return localCallback;
}
- InvokeDispatcher<CameraDeviceImpl.CaptureListener> localSink =
- new InvokeDispatcher<>(localListener);
+ InvokeDispatcher<CameraDeviceImpl.CaptureCallback> localSink =
+ new InvokeDispatcher<>(localCallback);
- InvokeDispatcher<CaptureListener> userListenerSink =
- new InvokeDispatcher<>(listener);
- HandlerDispatcher<CaptureListener> handlerPassthrough =
- new HandlerDispatcher<>(userListenerSink, handler);
- DuckTypingDispatcher<CameraDeviceImpl.CaptureListener, CaptureListener> duckToSession
- = new DuckTypingDispatcher<>(handlerPassthrough, CaptureListener.class);
- ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureListener, CameraCaptureSessionImpl>
+ InvokeDispatcher<CaptureCallback> userCallbackSink =
+ new InvokeDispatcher<>(callback);
+ HandlerDispatcher<CaptureCallback> handlerPassthrough =
+ new HandlerDispatcher<>(userCallbackSink, handler);
+ DuckTypingDispatcher<CameraDeviceImpl.CaptureCallback, CaptureCallback> duckToSession
+ = new DuckTypingDispatcher<>(handlerPassthrough, CaptureCallback.class);
+ ArgumentReplacingDispatcher<CameraDeviceImpl.CaptureCallback, CameraCaptureSessionImpl>
replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession,
/*argumentIndex*/0, this);
- BroadcastDispatcher<CameraDeviceImpl.CaptureListener> broadcaster =
- new BroadcastDispatcher<CameraDeviceImpl.CaptureListener>(
+ BroadcastDispatcher<CameraDeviceImpl.CaptureCallback> broadcaster =
+ new BroadcastDispatcher<CameraDeviceImpl.CaptureCallback>(
replaceDeviceWithSession,
localSink);
- return new ListenerProxies.DeviceCaptureListenerProxy(broadcaster);
+ return new CallbackProxies.DeviceCaptureCallbackProxy(broadcaster);
}
/**
*
- * Create an internal state listener, to be invoked on the mDeviceHandler
+ * Create an internal state callback, to be invoked on the mDeviceHandler
*
* <p>It has a few behaviors:
* <ul>
@@ -443,10 +443,10 @@
* </ul>
* </p>
* */
- CameraDeviceImpl.StateListenerKK getDeviceStateListener() {
+ CameraDeviceImpl.StateCallbackKK getDeviceStateCallback() {
final CameraCaptureSession session = this;
- return new CameraDeviceImpl.StateListenerKK() {
+ return new CameraDeviceImpl.StateCallbackKK() {
private boolean mBusy = false;
private boolean mActive = false;
@@ -471,7 +471,7 @@
mIdleDrainer.taskStarted();
mActive = true;
- mStateListener.onActive(session);
+ mStateCallback.onActive(session);
}
@Override
@@ -507,7 +507,7 @@
mBusy = false;
mActive = false;
- mStateListener.onReady(session);
+ mStateCallback.onReady(session);
}
@Override
@@ -629,7 +629,7 @@
// Fast path: A new capture session has replaced this one; don't unconfigure.
if (mSkipUnconfigure) {
- mStateListener.onClosed(CameraCaptureSessionImpl.this);
+ mStateCallback.onClosed(CameraCaptureSessionImpl.this);
return;
}
@@ -655,7 +655,7 @@
public void onDrained() {
synchronized (CameraCaptureSessionImpl.this) {
// The device has finished unconfiguring. It's now fully closed.
- mStateListener.onClosed(CameraCaptureSessionImpl.this);
+ mStateCallback.onClosed(CameraCaptureSessionImpl.this);
}
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index f5666bf..f011d60 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -64,17 +64,17 @@
private final Object mInterfaceLock = new Object();
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
- private final StateListener mDeviceListener;
- private volatile StateListenerKK mSessionStateListener;
+ private final StateCallback mDeviceCallback;
+ private volatile StateCallbackKK mSessionStateCallback;
private final Handler mDeviceHandler;
private volatile boolean mClosing = false;
private boolean mInError = false;
private boolean mIdle = true;
- /** map request IDs to listener/request data */
- private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
- new SparseArray<CaptureListenerHolder>();
+ /** map request IDs to callback/request data */
+ private final SparseArray<CaptureCallbackHolder> mCaptureCallbackMap =
+ new SparseArray<CaptureCallbackHolder>();
private int mRepeatingRequestId = REQUEST_ID_NONE;
private final ArrayList<Integer> mRepeatingRequestIdDeletedList = new ArrayList<Integer>();
@@ -106,30 +106,30 @@
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onOpened(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onOpened(CameraDeviceImpl.this);
}
- mDeviceListener.onOpened(CameraDeviceImpl.this);
+ mDeviceCallback.onOpened(CameraDeviceImpl.this);
}
};
private final Runnable mCallOnUnconfigured = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onUnconfigured(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onUnconfigured(CameraDeviceImpl.this);
}
}
};
@@ -137,14 +137,14 @@
private final Runnable mCallOnActive = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onActive(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onActive(CameraDeviceImpl.this);
}
}
};
@@ -152,14 +152,14 @@
private final Runnable mCallOnBusy = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onBusy(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onBusy(CameraDeviceImpl.this);
}
}
};
@@ -172,14 +172,14 @@
if (mClosedOnce) {
throw new AssertionError("Don't post #onClosed more than once");
}
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onClosed(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onClosed(CameraDeviceImpl.this);
}
- mDeviceListener.onClosed(CameraDeviceImpl.this);
+ mDeviceCallback.onClosed(CameraDeviceImpl.this);
mClosedOnce = true;
}
};
@@ -187,14 +187,14 @@
private final Runnable mCallOnIdle = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onIdle(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onIdle(CameraDeviceImpl.this);
}
}
};
@@ -202,26 +202,26 @@
private final Runnable mCallOnDisconnected = new Runnable() {
@Override
public void run() {
- StateListenerKK sessionListener = null;
+ StateCallbackKK sessionCallback = null;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- sessionListener = mSessionStateListener;
+ sessionCallback = mSessionStateCallback;
}
- if (sessionListener != null) {
- sessionListener.onDisconnected(CameraDeviceImpl.this);
+ if (sessionCallback != null) {
+ sessionCallback.onDisconnected(CameraDeviceImpl.this);
}
- mDeviceListener.onDisconnected(CameraDeviceImpl.this);
+ mDeviceCallback.onDisconnected(CameraDeviceImpl.this);
}
};
- public CameraDeviceImpl(String cameraId, StateListener listener, Handler handler,
+ public CameraDeviceImpl(String cameraId, StateCallback callback, Handler handler,
CameraCharacteristics characteristics) {
- if (cameraId == null || listener == null || handler == null || characteristics == null) {
+ if (cameraId == null || callback == null || handler == null || characteristics == null) {
throw new IllegalArgumentException("Null argument given");
}
mCameraId = cameraId;
- mDeviceListener = listener;
+ mDeviceCallback = callback;
mDeviceHandler = handler;
mCharacteristics = characteristics;
@@ -263,28 +263,28 @@
/**
* Call to indicate failed connection to a remote camera device.
*
- * <p>This places the camera device in the error state and informs the listener.
+ * <p>This places the camera device in the error state and informs the callback.
* Use in place of setRemoteDevice() when startup fails.</p>
*/
public void setRemoteFailure(final CameraRuntimeException failure) {
- int failureCode = StateListener.ERROR_CAMERA_DEVICE;
+ int failureCode = StateCallback.ERROR_CAMERA_DEVICE;
boolean failureIsError = true;
switch (failure.getReason()) {
case CameraAccessException.CAMERA_IN_USE:
- failureCode = StateListener.ERROR_CAMERA_IN_USE;
+ failureCode = StateCallback.ERROR_CAMERA_IN_USE;
break;
case CameraAccessException.MAX_CAMERAS_IN_USE:
- failureCode = StateListener.ERROR_MAX_CAMERAS_IN_USE;
+ failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE;
break;
case CameraAccessException.CAMERA_DISABLED:
- failureCode = StateListener.ERROR_CAMERA_DISABLED;
+ failureCode = StateCallback.ERROR_CAMERA_DISABLED;
break;
case CameraAccessException.CAMERA_DISCONNECTED:
failureIsError = false;
break;
case CameraAccessException.CAMERA_ERROR:
- failureCode = StateListener.ERROR_CAMERA_DEVICE;
+ failureCode = StateCallback.ERROR_CAMERA_DEVICE;
break;
default:
Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
@@ -298,9 +298,9 @@
@Override
public void run() {
if (isError) {
- mDeviceListener.onError(CameraDeviceImpl.this, code);
+ mDeviceCallback.onError(CameraDeviceImpl.this, code);
} else {
- mDeviceListener.onDisconnected(CameraDeviceImpl.this);
+ mDeviceCallback.onDisconnected(CameraDeviceImpl.this);
}
}
});
@@ -415,7 +415,7 @@
@Override
public void createCaptureSession(List<Surface> outputs,
- CameraCaptureSession.StateListener listener, Handler handler)
+ CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException {
synchronized(mInterfaceLock) {
if (DEBUG) {
@@ -445,7 +445,7 @@
// Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
CameraCaptureSessionImpl newSession =
- new CameraCaptureSessionImpl(outputs, listener, handler, this, mDeviceHandler,
+ new CameraCaptureSessionImpl(outputs, callback, handler, this, mDeviceHandler,
configureSuccess);
// TODO: wait until current session closes, then create the new session
@@ -455,16 +455,16 @@
throw pendingException;
}
- mSessionStateListener = mCurrentSession.getDeviceStateListener();
+ mSessionStateCallback = mCurrentSession.getDeviceStateCallback();
}
}
/**
* For use by backwards-compatibility code only.
*/
- public void setSessionListener(StateListenerKK sessionListener) {
+ public void setSessionListener(StateCallbackKK sessionCallback) {
synchronized(mInterfaceLock) {
- mSessionStateListener = sessionListener;
+ mSessionStateCallback = sessionCallback;
}
}
@@ -492,22 +492,22 @@
}
}
- public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
+ public int capture(CaptureRequest request, CaptureCallback callback, Handler handler)
throws CameraAccessException {
if (DEBUG) {
Log.d(TAG, "calling capture");
}
List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
requestList.add(request);
- return submitCaptureRequest(requestList, listener, handler, /*streaming*/false);
+ return submitCaptureRequest(requestList, callback, handler, /*streaming*/false);
}
- public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int captureBurst(List<CaptureRequest> requests, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (requests == null || requests.isEmpty()) {
throw new IllegalArgumentException("At least one request must be given");
}
- return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
+ return submitCaptureRequest(requests, callback, handler, /*streaming*/false);
}
/**
@@ -527,12 +527,12 @@
final int requestId, final long lastFrameNumber) {
// lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
// was never sent to HAL. Should trigger onCaptureSequenceAborted immediately.
- if (lastFrameNumber == CaptureListener.NO_FRAMES_CAPTURED) {
- final CaptureListenerHolder holder;
- int index = mCaptureListenerMap.indexOfKey(requestId);
- holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null;
+ if (lastFrameNumber == CaptureCallback.NO_FRAMES_CAPTURED) {
+ final CaptureCallbackHolder holder;
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index) : null;
if (holder != null) {
- mCaptureListenerMap.removeAt(index);
+ mCaptureCallbackMap.removeAt(index);
if (DEBUG) {
Log.v(TAG, String.format(
"remove holder for requestId %d, "
@@ -560,7 +560,7 @@
|| lastFrameNumber > Integer.MAX_VALUE) {
throw new AssertionError(lastFrameNumber + " cannot be cast to int");
}
- holder.getListener().onCaptureSequenceAborted(
+ holder.getCallback().onCaptureSequenceAborted(
CameraDeviceImpl.this,
requestId);
}
@@ -569,7 +569,7 @@
holder.getHandler().post(resultDispatch);
} else {
Log.w(TAG, String.format(
- "did not register listener to request %d",
+ "did not register callback to request %d",
requestId));
}
} else {
@@ -579,12 +579,12 @@
}
}
- private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener,
+ private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureCallback callback,
Handler handler, boolean repeating) throws CameraAccessException {
// Need a valid handler, or current thread needs to have a looper, if
- // listener is valid
- handler = checkHandler(handler, listener);
+ // callback is valid
+ handler = checkHandler(handler, callback);
// Make sure that there all requests have at least 1 surface; all surfaces are non-null
for (CaptureRequest request : requestList) {
@@ -622,8 +622,8 @@
return -1;
}
- if (listener != null) {
- mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
+ if (callback != null) {
+ mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
requestList, handler, repeating));
} else {
if (DEBUG) {
@@ -652,19 +652,19 @@
}
}
- public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ public int setRepeatingRequest(CaptureRequest request, CaptureCallback callback,
Handler handler) throws CameraAccessException {
List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
requestList.add(request);
- return submitCaptureRequest(requestList, listener, handler, /*streaming*/true);
+ return submitCaptureRequest(requestList, callback, handler, /*streaming*/true);
}
- public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int setRepeatingBurst(List<CaptureRequest> requests, CaptureCallback callback,
Handler handler) throws CameraAccessException {
if (requests == null || requests.isEmpty()) {
throw new IllegalArgumentException("At least one request must be given");
}
- return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
+ return submitCaptureRequest(requests, callback, handler, /*streaming*/true);
}
public void stopRepeating() throws CameraAccessException {
@@ -677,7 +677,7 @@
mRepeatingRequestId = REQUEST_ID_NONE;
// Queue for deletion after in-flight requests finish
- if (mCaptureListenerMap.get(requestId) != null) {
+ if (mCaptureCallbackMap.get(requestId) != null) {
mRepeatingRequestIdDeletedList.add(requestId);
}
@@ -782,11 +782,11 @@
}
/**
- * <p>A listener for tracking the progress of a {@link CaptureRequest}
+ * <p>A callback for tracking the progress of a {@link CaptureRequest}
* submitted to the camera device.</p>
*
*/
- public static abstract class CaptureListener {
+ public static abstract class CaptureCallback {
/**
* This constant is used to indicate that no images were captured for
@@ -803,7 +803,7 @@
* @see android.media.MediaActionSound
*/
public void onCaptureStarted(CameraDevice camera,
- CaptureRequest request, long timestamp) {
+ CaptureRequest request, long timestamp, long frameNumber) {
// default empty implementation
}
@@ -848,9 +848,9 @@
}
/**
- * This method is called independently of the others in CaptureListener,
+ * This method is called independently of the others in CaptureCallback,
* when a capture sequence finishes and all {@link CaptureResult}
- * or {@link CaptureFailure} for it have been returned via this listener.
+ * or {@link CaptureFailure} for it have been returned via this callback.
*/
public void onCaptureSequenceCompleted(CameraDevice camera,
int sequenceId, long frameNumber) {
@@ -858,9 +858,9 @@
}
/**
- * This method is called independently of the others in CaptureListener,
+ * This method is called independently of the others in CaptureCallback,
* when a capture sequence aborts before any {@link CaptureResult}
- * or {@link CaptureFailure} for it have been returned via this listener.
+ * or {@link CaptureFailure} for it have been returned via this callback.
*/
public void onCaptureSequenceAborted(CameraDevice camera,
int sequenceId) {
@@ -869,10 +869,10 @@
}
/**
- * A listener for notifications about the state of a camera device, adding in the callbacks that
+ * A callback for notifications about the state of a camera device, adding in the callbacks that
* were part of the earlier KK API design, but now only used internally.
*/
- public static abstract class StateListenerKK extends StateListener {
+ public static abstract class StateCallbackKK extends StateCallback {
/**
* The method called when a camera device has no outputs configured.
*
@@ -908,31 +908,31 @@
}
}
- static class CaptureListenerHolder {
+ static class CaptureCallbackHolder {
private final boolean mRepeating;
- private final CaptureListener mListener;
+ private final CaptureCallback mCallback;
private final List<CaptureRequest> mRequestList;
private final Handler mHandler;
- CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList,
+ CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
Handler handler, boolean repeating) {
- if (listener == null || handler == null) {
+ if (callback == null || handler == null) {
throw new UnsupportedOperationException(
- "Must have a valid handler and a valid listener");
+ "Must have a valid handler and a valid callback");
}
mRepeating = repeating;
mHandler = handler;
mRequestList = new ArrayList<CaptureRequest>(requestList);
- mListener = listener;
+ mCallback = callback;
}
public boolean isRepeating() {
return mRepeating;
}
- public CaptureListener getListener() {
- return mListener;
+ public CaptureCallback getCallback() {
+ return mCallback;
}
public CaptureRequest getRequest(int subsequenceId) {
@@ -1071,20 +1071,20 @@
final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
if (frameNumberRequestPair.getKey() <= completedFrameNumber) {
- // remove request from mCaptureListenerMap
+ // remove request from mCaptureCallbackMap
final int requestId = frameNumberRequestPair.getValue();
- final CaptureListenerHolder holder;
+ final CaptureCallbackHolder holder;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) {
Log.w(TAG, "Camera closed while checking sequences");
return;
}
- int index = mCaptureListenerMap.indexOfKey(requestId);
- holder = (index >= 0) ? mCaptureListenerMap.valueAt(index)
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ holder = (index >= 0) ? mCaptureCallbackMap.valueAt(index)
: null;
if (holder != null) {
- mCaptureListenerMap.removeAt(index);
+ mCaptureCallbackMap.removeAt(index);
if (DEBUG) {
Log.v(TAG, String.format(
"remove holder for requestId %d, "
@@ -1114,7 +1114,7 @@
throw new AssertionError(lastFrameNumber
+ " cannot be cast to int");
}
- holder.getListener().onCaptureSequenceCompleted(
+ holder.getCallback().onCaptureSequenceCompleted(
CameraDeviceImpl.this,
requestId,
lastFrameNumber);
@@ -1146,13 +1146,13 @@
/**
* Camera has encountered a device-level error
- * Matches CameraDevice.StateListener#ERROR_CAMERA_DEVICE
+ * Matches CameraDevice.StateCallback#ERROR_CAMERA_DEVICE
*/
static final int ERROR_CAMERA_DEVICE = 1;
/**
* Camera has encountered a service-level error
- * Matches CameraDevice.StateListener#ERROR_CAMERA_SERVICE
+ * Matches CameraDevice.StateCallback#ERROR_CAMERA_SERVICE
*/
static final int ERROR_CAMERA_SERVICE = 2;
@@ -1204,7 +1204,7 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()) {
- mDeviceListener.onError(CameraDeviceImpl.this, errorCode);
+ mDeviceCallback.onError(CameraDeviceImpl.this, errorCode);
}
}
};
@@ -1237,16 +1237,18 @@
@Override
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
+ final long frameNumber = resultExtras.getFrameNumber();
+
if (DEBUG) {
- Log.d(TAG, "Capture started for id " + requestId);
+ Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber);
}
- final CaptureListenerHolder holder;
+ final CaptureCallbackHolder holder;
synchronized(mInterfaceLock) {
if (mRemoteDevice == null) return; // Camera already closed
- // Get the listener for this frame ID, if there is one
- holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+ // Get the callback for this frame ID, if there is one
+ holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
if (holder == null) {
return;
@@ -1260,10 +1262,10 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()) {
- holder.getListener().onCaptureStarted(
+ holder.getCallback().onCaptureStarted(
CameraDeviceImpl.this,
holder.getRequest(resultExtras.getSubsequenceId()),
- timestamp);
+ timestamp, frameNumber);
}
}
});
@@ -1290,13 +1292,13 @@
result.set(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE,
getCharacteristics().get(CameraCharacteristics.LENS_INFO_SHADING_MAP_SIZE));
- final CaptureListenerHolder holder =
- CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+ final CaptureCallbackHolder holder =
+ CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
boolean isPartialResult =
(resultExtras.getPartialResultCount() < mTotalPartialCount);
- // Check if we have a listener for this
+ // Check if we have a callback for this
if (holder == null) {
if (DEBUG) {
Log.d(TAG,
@@ -1336,7 +1338,7 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()){
- holder.getListener().onCaptureProgressed(
+ holder.getCallback().onCaptureProgressed(
CameraDeviceImpl.this,
request,
resultAsCapture);
@@ -1357,7 +1359,7 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()){
- holder.getListener().onCaptureCompleted(
+ holder.getCallback().onCaptureCompleted(
CameraDeviceImpl.this,
request,
resultAsCapture);
@@ -1388,8 +1390,8 @@
final int requestId = resultExtras.getRequestId();
final int subsequenceId = resultExtras.getSubsequenceId();
final long frameNumber = resultExtras.getFrameNumber();
- final CaptureListenerHolder holder =
- CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
+ final CaptureCallbackHolder holder =
+ CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
final CaptureRequest request = holder.getRequest(subsequenceId);
@@ -1420,7 +1422,7 @@
@Override
public void run() {
if (!CameraDeviceImpl.this.isClosed()){
- holder.getListener().onCaptureFailed(
+ holder.getCallback().onCaptureFailed(
CameraDeviceImpl.this,
request,
failure);
@@ -1460,12 +1462,12 @@
}
/**
- * Default handler management, conditional on there being a listener.
+ * Default handler management, conditional on there being a callback.
*
- * <p>If the listener isn't null, check the handler, otherwise pass it through.</p>
+ * <p>If the callback isn't null, check the handler, otherwise pass it through.</p>
*/
- static <T> Handler checkHandler(Handler handler, T listener) {
- if (listener != null) {
+ static <T> Handler checkHandler(Handler handler, T callback) {
+ if (callback != null) {
return checkHandler(handler);
}
return handler;
diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
index 06521cf..2c584ef 100644
--- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
@@ -121,9 +121,10 @@
* Create a new GL thread and renderer.
*
* @param cameraId the camera id for this thread.
+ * @param facing direction the camera is facing.
*/
- public GLThreadManager(int cameraId) {
- mTextureRenderer = new SurfaceTextureRenderer();
+ public GLThreadManager(int cameraId, int facing) {
+ mTextureRenderer = new SurfaceTextureRenderer(facing);
TAG = String.format("CameraDeviceGLThread-%d", cameraId);
mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb);
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
index d0a3a3f..d5ec71a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyFocusStateMapper.java
@@ -114,21 +114,24 @@
currentAfRun = mAfRun;
}
- mCamera.setAutoFocusMoveCallback(new Camera.AutoFocusMoveCallback() {
+ Camera.AutoFocusMoveCallback afMoveCallback = new Camera.AutoFocusMoveCallback() {
@Override
public void onAutoFocusMoving(boolean start, Camera camera) {
synchronized (mLock) {
int latestAfRun = mAfRun;
if (VERBOSE) {
- Log.v(TAG, "onAutoFocusMoving - start " + start + " latest AF run " +
- latestAfRun + ", last AF run " + currentAfRun);
+ Log.v(TAG,
+ "onAutoFocusMoving - start " + start + " latest AF run " +
+ latestAfRun + ", last AF run " + currentAfRun
+ );
}
if (currentAfRun != latestAfRun) {
Log.d(TAG,
"onAutoFocusMoving - ignoring move callbacks from old af run"
- + currentAfRun);
+ + currentAfRun
+ );
return;
}
@@ -151,9 +154,19 @@
mAfState = newAfState;
}
}
- });
+ };
+
+ // Only set move callback if we can call autofocus.
+ switch (afMode) {
+ case Parameters.FOCUS_MODE_AUTO:
+ case Parameters.FOCUS_MODE_MACRO:
+ case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
+ case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
+ mCamera.setAutoFocusMoveCallback(afMoveCallback);
+ }
}
+
// AF Locking
switch (afTrigger) {
case CONTROL_AF_TRIGGER_START:
@@ -167,6 +180,7 @@
case Parameters.FOCUS_MODE_CONTINUOUS_PICTURE:
case Parameters.FOCUS_MODE_CONTINUOUS_VIDEO:
afStateAfterStart = CONTROL_AF_STATE_PASSIVE_SCAN;
+ break;
default:
// EDOF, INFINITY
afStateAfterStart = CONTROL_AF_STATE_INACTIVE;
@@ -183,6 +197,11 @@
"new AF run is " + currentAfRun);
}
+ // Avoid calling autofocus unless we are in a state that supports calling this.
+ if (afStateAfterStart == CONTROL_AF_STATE_INACTIVE) {
+ break;
+ }
+
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index a8d1018..3c0e0e4 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -675,15 +675,13 @@
* request.availableRequestKeys
*/
{
- CaptureRequest.Key<?> availableKeys[] = new CaptureRequest.Key<?>[] {
+ CaptureRequest.Key<?> defaultAvailableKeys[] = new CaptureRequest.Key<?>[] {
CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
CaptureRequest.CONTROL_AE_LOCK,
CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_REGIONS,
CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_REGIONS,
CaptureRequest.CONTROL_AF_TRIGGER,
CaptureRequest.CONTROL_AWB_LOCK,
CaptureRequest.CONTROL_AWB_MODE,
@@ -704,21 +702,32 @@
CaptureRequest.SCALER_CROP_REGION,
CaptureRequest.STATISTICS_FACE_DETECT_MODE,
};
- m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableKeys));
+ ArrayList<CaptureRequest.Key<?>> availableKeys =
+ new ArrayList<CaptureRequest.Key<?>>(Arrays.asList(defaultAvailableKeys));
+
+ if (p.getMaxNumMeteringAreas() > 0) {
+ availableKeys.add(CaptureRequest.CONTROL_AE_REGIONS);
+ }
+ if (p.getMaxNumFocusAreas() > 0) {
+ availableKeys.add(CaptureRequest.CONTROL_AF_REGIONS);
+ }
+
+ CaptureRequest.Key<?> availableRequestKeys[] =
+ new CaptureRequest.Key<?>[availableKeys.size()];
+ availableKeys.toArray(availableRequestKeys);
+ m.set(REQUEST_AVAILABLE_REQUEST_KEYS, getTagsForKeys(availableRequestKeys));
}
/*
* request.availableResultKeys
*/
{
- CaptureResult.Key<?> availableKeys[] = new CaptureResult.Key<?>[] {
+ CaptureResult.Key<?> defaultAvailableKeys[] = new CaptureResult.Key<?>[] {
CaptureResult.CONTROL_AE_ANTIBANDING_MODE ,
CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION ,
CaptureResult.CONTROL_AE_LOCK ,
CaptureResult.CONTROL_AE_MODE ,
- CaptureResult.CONTROL_AE_REGIONS ,
CaptureResult.CONTROL_AF_MODE ,
- CaptureResult.CONTROL_AF_REGIONS ,
CaptureResult.CONTROL_AF_STATE ,
CaptureResult.CONTROL_AWB_MODE ,
CaptureResult.CONTROL_AWB_LOCK ,
@@ -737,7 +746,20 @@
CaptureResult.STATISTICS_FACE_DETECT_MODE ,
// CaptureResult.STATISTICS_FACES ,
};
- m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableKeys));
+ List<CaptureResult.Key<?>> availableKeys =
+ new ArrayList<CaptureResult.Key<?>>(Arrays.asList(defaultAvailableKeys));
+
+ if (p.getMaxNumMeteringAreas() > 0) {
+ availableKeys.add(CaptureResult.CONTROL_AE_REGIONS);
+ }
+ if (p.getMaxNumFocusAreas() > 0) {
+ availableKeys.add(CaptureResult.CONTROL_AF_REGIONS);
+ }
+
+ CaptureResult.Key<?> availableResultKeys[] =
+ new CaptureResult.Key<?>[availableKeys.size()];
+ availableKeys.toArray(availableResultKeys);
+ m.set(REQUEST_AVAILABLE_RESULT_KEYS, getTagsForKeys(availableResultKeys));
}
/*
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 4c4ad0d..42ee4fa 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -122,7 +122,10 @@
activeArray, zoomData, aeRegions, maxNumMeteringAreas,
/*regionName*/"AE");
- params.setMeteringAreas(meteringAreaList);
+ // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+ if (maxNumMeteringAreas > 0) {
+ params.setMeteringAreas(meteringAreaList);
+ }
}
// afRegions
@@ -133,7 +136,10 @@
activeArray, zoomData, afRegions, maxNumFocusAreas,
/*regionName*/"AF");
- params.setFocusAreas(focusAreaList);
+ // WAR: for b/17252693, some devices can't handle params.setFocusAreas(null).
+ if (maxNumFocusAreas > 0) {
+ params.setFocusAreas(focusAreaList);
+ }
}
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index 090a822..ddaa6ee 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -322,7 +322,7 @@
}
// control.aeRegions
- {
+ if (p.getMaxNumMeteringAreas() > 0) {
if (VERBOSE) {
String meteringAreas = p.get("metering-areas");
Log.v(TAG, "mapAe - parameter dump; metering-areas: " + meteringAreas);
@@ -342,7 +342,7 @@
m.set(CaptureResult.CONTROL_AF_MODE, convertLegacyAfMode(p.getFocusMode()));
// control.afRegions
- {
+ if (p.getMaxNumFocusAreas() > 0) {
if (VERBOSE) {
String focusAreas = p.get("focus-areas");
Log.v(TAG, "mapAe - parameter dump; focus-areas: " + focusAreas);
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index eb8debb..e6ff17b 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -399,7 +399,7 @@
// TODO: Detect and optimize single-output paths here to skip stream teeing.
if (mGLThreadManager == null) {
- mGLThreadManager = new GLThreadManager(mCameraId);
+ mGLThreadManager = new GLThreadManager(mCameraId, facing);
mGLThreadManager.start();
}
mGLThreadManager.waitUntilStarted();
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index b1b0f9b..a35883c 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -18,6 +18,7 @@
import android.graphics.ImageFormat;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraCharacteristics;
import android.os.Environment;
import android.opengl.EGL14;
import android.opengl.EGLConfig;
@@ -80,7 +81,18 @@
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
- private final float[] mTriangleVerticesData = {
+
+ // Sampling is mirrored across the vertical axis to undo horizontal flip from the front camera
+ private static final float[] sFrontCameraTriangleVertices = {
+ // X, Y, Z, U, V
+ -1.0f, -1.0f, 0, 1.f, 0.f,
+ 1.0f, -1.0f, 0, 0.f, 0.f,
+ -1.0f, 1.0f, 0, 1.f, 1.f,
+ 1.0f, 1.0f, 0, 0.f, 1.f,
+ };
+
+ // Sampling is 1:1 for a straight copy for the back camera
+ private static final float[] sBackCameraTriangleVertices = {
// X, Y, Z, U, V
-1.0f, -1.0f, 0, 0.f, 0.f,
1.0f, -1.0f, 0, 1.f, 0.f,
@@ -135,10 +147,16 @@
private PerfMeasurement mPerfMeasurer = null;
private static final String LEGACY_PERF_PROPERTY = "persist.camera.legacy_perf";
- public SurfaceTextureRenderer() {
- mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length *
- FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
- mTriangleVertices.put(mTriangleVerticesData).position(0);
+ public SurfaceTextureRenderer(int facing) {
+ if (facing == CameraCharacteristics.LENS_FACING_BACK) {
+ mTriangleVertices = ByteBuffer.allocateDirect(sBackCameraTriangleVertices.length *
+ FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTriangleVertices.put(sBackCameraTriangleVertices).position(0);
+ } else {
+ mTriangleVertices = ByteBuffer.allocateDirect(sFrontCameraTriangleVertices.length *
+ FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTriangleVertices.put(sFrontCameraTriangleVertices).position(0);
+ }
Matrix.setIdentityM(mSTMatrix, 0);
}
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c0b7967..5d226e3 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -142,7 +142,7 @@
* or in {@link PixelFormat} (and there is no possibility of collision).</p>
*
* <p>Formats listed in this array are guaranteed to return true if queried with
- * {@link #isOutputSupportedFor(int).</p>
+ * {@link #isOutputSupportedFor(int)}.</p>
*
* @return an array of integer format
*
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 4b5ced9..30f3576 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -55,10 +55,29 @@
public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
/**
+ * Message used by TV to receive volume status from Audio Receiver. It should check volume value
+ * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the
+ * value is in range of [0,100], it is current volume of Audio Receiver. And there is another
+ * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute.
+ */
+ public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2;
+
+ /**
* Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
* the message to display on screen.
*/
public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
+ /**
+ * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value
+ * of the message.
+ */
+ public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 =
+ "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
+
+ /**
+ * Volume value for mute state.
+ */
+ public static final int AVR_VOLUME_MUTED = 101;
public static final int POWER_STATUS_UNKNOWN = -1;
public static final int POWER_STATUS_ON = 0;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 7a49eb5..7390e2b 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -480,7 +480,7 @@
int capturePreambleMs = in.readInt();
boolean triggerInData = in.readByte() == 1;
AudioFormat captureFormat = null;
- if (triggerInData) {
+ if (in.readByte() == 1) {
int sampleRate = in.readInt();
int encoding = in.readInt();
int channelMask = in.readInt();
@@ -508,7 +508,8 @@
dest.writeInt(captureSession);
dest.writeInt(captureDelayMs);
dest.writeInt(capturePreambleMs);
- if (triggerInData && (captureFormat != null)) {
+ dest.writeByte((byte) (triggerInData ? 1 : 0));
+ if (captureFormat != null) {
dest.writeByte((byte)1);
dest.writeInt(captureFormat.getSampleRate());
dest.writeInt(captureFormat.getEncoding());
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3c219fd..70b402d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1298,7 +1298,7 @@
}
/**
- * Callback for use with {@link ConnectivityManager#registerDefaultNetworkActiveListener}
+ * Callback for use with {@link ConnectivityManager#addDefaultNetworkActiveListener}
* to find out when the system default network has gone in to a high power state.
*/
public interface OnNetworkActiveListener {
@@ -1340,7 +1340,7 @@
*
* @param l The listener to be told when the network is active.
*/
- public void registerDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
+ public void addDefaultNetworkActiveListener(final OnNetworkActiveListener l) {
INetworkActivityListener rl = new INetworkActivityListener.Stub() {
@Override
public void onNetworkActive() throws RemoteException {
@@ -1357,11 +1357,11 @@
/**
* Remove network active listener previously registered with
- * {@link #registerDefaultNetworkActiveListener}.
+ * {@link #addDefaultNetworkActiveListener}.
*
* @param l Previously registered listener.
*/
- public void unregisterDefaultNetworkActiveListener(OnNetworkActiveListener l) {
+ public void removeDefaultNetworkActiveListener(OnNetworkActiveListener l) {
INetworkActivityListener rl = mNetworkActivityListeners.get(l);
if (rl == null) {
throw new IllegalArgumentException("Listener not registered: " + l);
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index f9a25f9..c387055 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -274,7 +274,6 @@
/**
* Implement the Parcelable interface.
- * @hide
*/
public int describeContents() {
return 0;
@@ -282,7 +281,6 @@
/**
* Implement the Parcelable interface.
- * @hide
*/
public void writeToParcel(Parcel dest, int flags) {
dest.writeByteArray(address.getAddress());
@@ -293,7 +291,6 @@
/**
* Implement the Parcelable interface.
- * @hide
*/
public static final Creator<LinkAddress> CREATOR =
new Creator<LinkAddress>() {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 83bdfaa..5a09b46 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -52,6 +52,9 @@
* @hide
*/
public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
+ if (nc == null) {
+ throw new NullPointerException();
+ }
requestId = rId;
networkCapabilities = nc;
this.legacyType = legacyType;
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 7ea6bae..1534e2c 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -334,10 +334,6 @@
dest.writeStringArray(mParsedExclusionList);
}
- /**
- * Implement the Parcelable interface.
- * @hide
- */
public static final Creator<ProxyInfo> CREATOR =
new Creator<ProxyInfo>() {
public ProxyInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fe9f79b..461469c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1667,7 +1667,7 @@
*/
public abstract long[] getChargeStepDurationsArray();
- public abstract Map<String, ? extends LongCounter> getWakeupReasonStats();
+ public abstract Map<String, ? extends Timer> getWakeupReasonStats();
public abstract Map<String, ? extends Timer> getKernelWakelockStats();
@@ -2045,11 +2045,15 @@
sb.toString());
}
}
- Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
+ Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
if (wakeupReasons.size() > 0) {
- for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
+ for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+ // Not doing the regular wake lock formatting to remain compatible
+ // with the old checkin format.
+ long totalTimeMicros = ent.getValue().getTotalTimeLocked(rawRealtime, which);
+ int count = ent.getValue().getCountLocked(which);
dumpLine(pw, 0 /* uid */, category, WAKEUP_REASON_DATA,
- "\"" + ent.getKey() + "\"", ent.getValue().getCountLocked(which));
+ "\"" + ent.getKey() + "\"", (totalTimeMicros + 500) / 1000, count);
}
}
}
@@ -2921,14 +2925,14 @@
pw.println();
}
- Map<String, ? extends LongCounter> wakeupReasons = getWakeupReasonStats();
+ Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
if (wakeupReasons.size() > 0) {
pw.print(prefix); pw.println(" All wakeup reasons:");
final ArrayList<TimerEntry> reasons = new ArrayList<TimerEntry>();
- for (Map.Entry<String, ? extends LongCounter> ent : wakeupReasons.entrySet()) {
- BatteryStats.LongCounter counter = ent.getValue();
- reasons.add(new TimerEntry(ent.getKey(), 0, null,
- ent.getValue().getCountLocked(which)));
+ for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+ Timer timer = ent.getValue();
+ reasons.add(new TimerEntry(ent.getKey(), 0, timer,
+ timer.getCountLocked(which)));
}
Collections.sort(reasons, timerComparator);
for (int i=0; i<reasons.size(); i++) {
@@ -2938,9 +2942,8 @@
sb.append(prefix);
sb.append(" Wakeup reason ");
sb.append(timer.mName);
- sb.append(": ");
- formatTimeMs(sb, timer.mTime);
- sb.append("realtime");
+ printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": ");
+ sb.append(" realtime");
pw.println(sb.toString());
}
pw.println();
@@ -3138,7 +3141,7 @@
}
Map<String, ? extends Timer> jobs = u.getJobStats();
- if (syncs.size() > 0) {
+ if (jobs.size() > 0) {
for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
Timer timer = ent.getValue();
// Convert from microseconds to milliseconds with rounding
@@ -3952,7 +3955,7 @@
prepareForDumpLocked();
dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA,
- "10", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
+ "11", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion());
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index b0e0b49..1e0dc53 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -541,7 +541,7 @@
* Intent.</li>
* </ul>
*/
- public static final int L = CUR_DEVELOPMENT;
+ public static final int L = 21;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 3252d19..a9aa570 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,6 +17,8 @@
package android.os;
import android.util.ArrayMap;
+import android.util.Size;
+import android.util.SizeF;
import android.util.SparseArray;
import java.io.Serializable;
@@ -335,6 +337,30 @@
}
/**
+ * Inserts a Size value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Size object, or null
+ */
+ public void putSize(String key, Size value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a SizeF value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a SizeF object, or null
+ */
+ public void putSizeF(String key, SizeF value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
* Inserts an array of Parcelable values into the mapping of this Bundle,
* replacing any existing value for the given key. Either key or value may
* be null.
@@ -712,6 +738,44 @@
* value is explicitly associated with the key.
*
* @param key a String, or null
+ * @return a Size value, or null
+ */
+ public Size getSize(String key) {
+ unparcel();
+ final Object o = mMap.get(key);
+ try {
+ return (Size) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Size", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a Size value, or null
+ */
+ public SizeF getSizeF(String key) {
+ unparcel();
+ final Object o = mMap.get(key);
+ try {
+ return (SizeF) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "SizeF", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
* @return a Bundle value, or null
*/
public Bundle getBundle(String key) {
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index 022a106..0acf24b 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -75,6 +75,13 @@
return mClosed;
}
+ public void forceClose() {
+ IoUtils.closeQuietly(mTarget);
+ IoUtils.closeQuietly(mServer);
+ IoUtils.closeQuietly(mClient);
+ mClosed = true;
+ }
+
public void setTargetFile(FileDescriptor target) {
mTarget = target;
}
@@ -89,7 +96,6 @@
try {
while (IoBridge.read(mServer, temp, 0, MSG_LENGTH) == MSG_LENGTH) {
final int cmd = Memory.peekInt(temp, 0, ByteOrder.BIG_ENDIAN);
-
if (cmd == CMD_WRITE) {
// Shuttle data into local file
int len = Memory.peekInt(temp, 4, ByteOrder.BIG_ENDIAN);
@@ -118,15 +124,10 @@
}
}
- } catch (ErrnoException e) {
- Log.wtf(TAG, "Failed during bridge", e);
- } catch (IOException e) {
+ } catch (ErrnoException | IOException e) {
Log.wtf(TAG, "Failed during bridge", e);
} finally {
- IoUtils.closeQuietly(mTarget);
- IoUtils.closeQuietly(mServer);
- IoUtils.closeQuietly(mClient);
- mClosed = true;
+ forceClose();
}
}
@@ -151,6 +152,7 @@
writeCommandAndBlock(CMD_CLOSE, "close()");
} finally {
IoBridge.closeAndSignalBlockedThreads(mClient);
+ IoUtils.closeQuietly(mClientPfd);
}
}
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 1a5811c..b6b70cc 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -113,6 +113,8 @@
private static final int MAX_POOL_SIZE = 50;
+ private static boolean gCheckRecycle = true;
+
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
@@ -256,6 +258,13 @@
return m;
}
+ /** @hide */
+ public static void updateCheckRecycle(int targetSdkVersion) {
+ if (targetSdkVersion < Build.VERSION_CODES.L) {
+ gCheckRecycle = false;
+ }
+ }
+
/**
* Return a Message instance to the global pool.
* <p>
@@ -266,8 +275,11 @@
*/
public void recycle() {
if (isInUse()) {
- throw new IllegalStateException("This message cannot be recycled because it "
- + "is still in use.");
+ if (gCheckRecycle) {
+ throw new IllegalStateException("This message cannot be recycled because it "
+ + "is still in use.");
+ }
+ return;
}
recycleUnchecked();
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 645d510..d1ad0ad 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -19,6 +19,8 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Size;
+import android.util.SizeF;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -224,6 +226,8 @@
private static final int VAL_BOOLEANARRAY = 23;
private static final int VAL_CHARSEQUENCEARRAY = 24;
private static final int VAL_PERSISTABLEBUNDLE = 25;
+ private static final int VAL_SIZE = 26;
+ private static final int VAL_SIZEF = 27;
// The initial int32 in a Binder call's reply Parcel header:
private static final int EX_SECURITY = -1;
@@ -672,6 +676,24 @@
}
/**
+ * Flatten a Size into the parcel at the current dataPosition(),
+ * growing dataCapacity() if needed.
+ */
+ public final void writeSize(Size val) {
+ writeInt(val.getWidth());
+ writeInt(val.getHeight());
+ }
+
+ /**
+ * Flatten a SizeF into the parcel at the current dataPosition(),
+ * growing dataCapacity() if needed.
+ */
+ public final void writeSizeF(SizeF val) {
+ writeFloat(val.getWidth());
+ writeFloat(val.getHeight());
+ }
+
+ /**
* Flatten a List into the parcel at the current dataPosition(), growing
* dataCapacity() if needed. The List values are written using
* {@link #writeValue} and must follow the specification there.
@@ -1293,6 +1315,12 @@
} else if (v instanceof PersistableBundle) {
writeInt(VAL_PERSISTABLEBUNDLE);
writePersistableBundle((PersistableBundle) v);
+ } else if (v instanceof Size) {
+ writeInt(VAL_SIZE);
+ writeSize((Size) v);
+ } else if (v instanceof SizeF) {
+ writeInt(VAL_SIZEF);
+ writeSizeF((SizeF) v);
} else {
Class<?> clazz = v.getClass();
if (clazz.isArray() && clazz.getComponentType() == Object.class) {
@@ -1699,6 +1727,24 @@
}
/**
+ * Read a Size from the parcel at the current dataPosition().
+ */
+ public final Size readSize() {
+ final int width = readInt();
+ final int height = readInt();
+ return new Size(width, height);
+ }
+
+ /**
+ * Read a SizeF from the parcel at the current dataPosition().
+ */
+ public final SizeF readSizeF() {
+ final float width = readFloat();
+ final float height = readFloat();
+ return new SizeF(width, height);
+ }
+
+ /**
* Read and return a byte[] object from the parcel.
*/
public final byte[] createByteArray() {
@@ -2160,6 +2206,12 @@
case VAL_PERSISTABLEBUNDLE:
return readPersistableBundle(loader);
+ case VAL_SIZE:
+ return readSize();
+
+ case VAL_SIZEF:
+ return readSizeF();
+
default:
int off = dataPosition() - 4;
throw new RuntimeException(
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index c3ac012..b2ebc31 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -468,6 +468,7 @@
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
* @param abi non-null the ABI this app should be started with.
+ * @param instructionSet null-ok the instruction set to use.
* @param zygoteArgs Additional arguments to supply to the zygote process.
*
* @return An object that describes the result of the attempt to start the process.
@@ -482,11 +483,12 @@
int targetSdkVersion,
String seInfo,
String abi,
+ String instructionSet,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
- abi, zygoteArgs);
+ abi, instructionSet, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -589,6 +591,7 @@
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
* @param abi the ABI the process should use.
+ * @param instructionSet null-ok the instruction set to use.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
@@ -601,6 +604,7 @@
int targetSdkVersion,
String seInfo,
String abi,
+ String instructionSet,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
@@ -660,6 +664,10 @@
argsForZygote.add("--seinfo=" + seInfo);
}
+ if (instructionSet != null) {
+ argsForZygote.add("--instruction-set=" + instructionSet);
+ }
+
argsForZygote.add(processClass);
if (extraArgs != null) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 59220e1..33fda4a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -22,10 +22,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Bitmap.Config;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
import android.util.Log;
@@ -46,190 +43,208 @@
private final Context mContext;
/**
- * Key for user restrictions. Specifies if a user is disallowed from adding and removing
- * accounts.
+ * Specifies if a user is disallowed from adding and removing accounts.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
/**
- * Key for user restrictions. Specifies if a user is disallowed from changing Wi-Fi
+ * Specifies if a user is disallowed from changing Wi-Fi
* access points. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_WIFI = "no_config_wifi";
/**
- * Key for user restrictions. Specifies if a user is disallowed from installing applications.
+ * Specifies if a user is disallowed from installing applications.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_INSTALL_APPS = "no_install_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from uninstalling applications.
+ * Specifies if a user is disallowed from uninstalling applications.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from toggling location sharing.
+ * Specifies if a user is disallowed from toggling location sharing.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
/**
- * Key for user restrictions. Specifies if a user is disallowed from enabling the
+ * Specifies if a user is disallowed from enabling the
* "Unknown Sources" setting, that allows installation of apps from unknown sources.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring bluetooth.
+ * Specifies if a user is disallowed from configuring bluetooth.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
/**
- * Key for user restrictions. Specifies if a user is disallowed from transferring files over
+ * Specifies if a user is disallowed from transferring files over
* USB. This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring user
+ * Specifies if a user is disallowed from configuring user
* credentials. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials";
/**
- * Key for user restrictions. Specifies if a user is disallowed from removing itself and other
+ * Specifies if a user is disallowed from removing itself and other
* users. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_REMOVE_USER = "no_remove_user";
/**
- * Key for user restrictions. Specifies if a user is disallowed from enabling or
+ * Specifies if a user is disallowed from enabling or
* accessing debugging features. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_DEBUGGING_FEATURES = "no_debugging_features";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring VPN.
+ * Specifies if a user is disallowed from configuring VPN.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_VPN = "no_config_vpn";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring Tethering
+ * Specifies if a user is disallowed from configuring Tethering
* & portable hotspots. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_TETHERING = "no_config_tethering";
/**
- * Key for user restrictions. Specifies if a user is disallowed from factory resetting
+ * Specifies if a user is disallowed from factory resetting
* from Settings. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p>
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_FACTORY_RESET = "no_factory_reset";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adding new users and
+ * Specifies if a user is disallowed from adding new users and
* profiles. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_ADD_USER = "no_add_user";
/**
- * Key for user restrictions. Specifies if a user is disallowed from disabling application
+ * Specifies if a user is disallowed from disabling application
* verification. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String ENSURE_VERIFY_APPS = "ensure_verify_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring cell
+ * Specifies if a user is disallowed from configuring cell
* broadcasts. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts";
/**
- * Key for user restrictions. Specifies if a user is disallowed from configuring mobile
+ * Specifies if a user is disallowed from configuring mobile
* networks. This can only be set by device owners. The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CONFIG_MOBILE_NETWORKS = "no_config_mobile_networks";
/**
- * Key for user restrictions. Specifies if a user is disallowed from modifying
+ * Specifies if a user is disallowed from modifying
* applications in Settings or launchers. The following actions will not be allowed when this
* restriction is enabled:
* <li>uninstalling apps</li>
@@ -240,69 +255,75 @@
* <li>clearing app defaults</li>
* <p>
* The default value is <code>false</code>.
- * <p>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_APPS_CONTROL = "no_control_apps";
/**
- * Key for user restrictions. Specifies if a user is disallowed from mounting
+ * Specifies if a user is disallowed from mounting
* physical external media. This can only be set by device owners. The default value is
* <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_MOUNT_PHYSICAL_MEDIA = "no_physical_media";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adjusting microphone
+ * Specifies if a user is disallowed from adjusting microphone
* volume. If set, the microphone will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_UNMUTE_MICROPHONE = "no_unmute_microphone";
/**
- * Key for user restrictions. Specifies if a user is disallowed from adjusting the master
+ * Specifies if a user is disallowed from adjusting the master
* volume. If set, the master volume will be muted. This can only be set by device owners.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_ADJUST_VOLUME = "no_adjust_volume";
/**
- * Key for user restrictions. Specifies that the user is not allowed to make outgoing
+ * Specifies that the user is not allowed to make outgoing
* phone calls. Emergency calls are still permitted.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_OUTGOING_CALLS = "no_outgoing_calls";
/**
- * Key for user restrictions. Specifies that the user is not allowed to send or receive
+ * Specifies that the user is not allowed to send or receive
* SMS messages. This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_SMS = "no_sms";
/**
- * Key for user restrictions. Specifies that windows besides app windows should not be
+ * Specifies that windows besides app windows should not be
* created. This will block the creation of the following types of windows.
* <li>{@link LayoutParams#TYPE_TOAST}</li>
* <li>{@link LayoutParams#TYPE_PHONE}</li>
@@ -312,25 +333,38 @@
* <li>{@link LayoutParams#TYPE_SYSTEM_OVERLAY}</li>
*
* <p>This can only be set by device owners. The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CREATE_WINDOWS = "no_create_windows";
/**
- * Key for user restrictions. Specifies if what is copied in the clipboard of this profile can
+ * Specifies if what is copied in the clipboard of this profile can
* be pasted in related profiles. Does not restrict if the clipboard of related profiles can be
* pasted in this profile.
* The default value is <code>false</code>.
- * <p/>
- * Type: Boolean
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
* @see #setUserRestrictions(Bundle)
* @see #getUserRestrictions()
*/
public static final String DISALLOW_CROSS_PROFILE_COPY_PASTE = "no_cross_profile_copy_paste";
+ /**
+ * Specifies if the user is not allowed to use NFC to beam out data from apps.
+ * The default value is <code>false</code>.
+ *
+ * <p/>Key for user restrictions.
+ * <p/>Type: Boolean
+ * @see #setUserRestrictions(Bundle)
+ * @see #getUserRestrictions()
+ */
+ public static final String DISALLOW_OUTGOING_BEAM = "no_outgoing_beam";
+
/** @hide */
public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
/** @hide */
@@ -660,6 +694,7 @@
try {
Bundle guestRestrictions = mService.getDefaultGuestRestrictions();
guestRestrictions.putBoolean(DISALLOW_SMS, true);
+ guestRestrictions.putBoolean(DISALLOW_INSTALL_UNKNOWN_SOURCES, true);
mService.setUserRestrictions(guestRestrictions, guest.id);
} catch (RemoteException re) {
Log.w(TAG, "Could not update guest restrictions");
@@ -837,46 +872,10 @@
* @param user The target user.
* @return A drawable that combines the original icon and a badge as
* determined by the system.
+ * @removed
*/
public Drawable getBadgedIconForUser(Drawable icon, UserHandle user) {
- final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
- if (badgeResId == 0) {
- return icon;
- }
- Drawable badgeIcon = mContext.getPackageManager()
- .getDrawable("system", badgeResId, null);
- return getBadgedDrawable(icon, badgeIcon, null, true);
- }
-
- /**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a badged copy of the given
- * icon to be able to distinguish it from the original icon.
- * <p>
- * If the original drawable is not a BitmapDrawable, then the original
- * drawable is returned.
- * </p>
- *
- * @param icon The icon to badge.
- * @param user The target user.
- * @return A drawable that combines the original icon and a badge as
- * determined by the system.
- *
- * @deprecation Use {@link #getBadgedIconForUser(
- * android.graphics.drawable.Drawable, UserHandle)}
- *
- * @hide
- */
- @Deprecated
- public Drawable getBadgedDrawableForUser(Drawable icon, UserHandle user) {
- int badgeResId = getBadgeResIdForUser(user.getIdentifier());
- if (badgeResId == 0) {
- return icon;
- } else {
- Drawable badgeIcon = mContext.getPackageManager()
- .getDrawable("system", badgeResId, null);
- return getBadgedDrawable(icon, badgeIcon, null, false);
- }
+ return mContext.getPackageManager().getUserBadgedIcon(icon, user);
}
/**
@@ -902,14 +901,12 @@
* the density of the display is used.
* @return A drawable that combines the original drawable and a badge as
* determined by the system.
+ * @removed
*/
public Drawable getBadgedDrawableForUser(Drawable badgedDrawable, UserHandle user,
Rect badgeLocation, int badgeDensity) {
- Drawable badgeDrawable = getBadgeForUser(user, badgeDensity);
- if (badgeDrawable == null) {
- return badgedDrawable;
- }
- return getBadgedDrawable(badgedDrawable, badgeDrawable, badgeLocation, true);
+ return mContext.getPackageManager().getUserBadgedDrawableForDensity(badgedDrawable, user,
+ badgeLocation, badgeDensity);
}
/**
@@ -922,114 +919,10 @@
* @param user The target user.
* @return A label that combines the original label and a badge as
* determined by the system.
+ * @removed
*/
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
- UserInfo userInfo = getUserIfProfile(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
- return Resources.getSystem().getString(
- R.string.managed_profile_label_badge, label);
- }
- return label;
- }
-
- /**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a drawable to use as a small
- * icon to include in a view to distinguish it from the original icon.
- *
- * @param user The target user.
- * @param density The optional desired density for the badge as per
- * {@link android.util.DisplayMetrics#densityDpi}. If not provided
- * the density of the current display is used.
- * @return the drawable or null if no drawable is required.
- * @hide
- */
- public Drawable getBadgeForUser(UserHandle user, int density) {
- UserInfo userInfo = getUserIfProfile(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
- if (density <= 0) {
- density = mContext.getResources().getDisplayMetrics().densityDpi;
- }
- return Resources.getSystem().getDrawableForDensity(
- com.android.internal.R.drawable.ic_corp_badge, density);
- }
- return null;
- }
-
- private int getBadgeResIdForUser(int userHandle) {
- // Return the framework-provided badge.
- UserInfo userInfo = getUserIfProfile(userHandle);
- if (userInfo != null && userInfo.isManagedProfile()) {
- return com.android.internal.R.drawable.ic_corp_icon_badge;
- }
- return 0;
- }
-
- /**
- * @return UserInfo for userHandle if it exists and is a profile of the current
- * user or null.
- */
- private UserInfo getUserIfProfile(int userHandle) {
- List<UserInfo> userProfiles = getProfiles(getUserHandle());
- for (UserInfo user : userProfiles) {
- if (user.id == userHandle) {
- return user;
- }
- }
- return null;
- }
-
- private Drawable getBadgedDrawable(Drawable badgedDrawable, Drawable badgeDrawable,
- Rect badgeLocation, boolean tryBadgeInPlace) {
- final int badgedWidth = badgedDrawable.getIntrinsicWidth();
- final int badgedHeight = badgedDrawable.getIntrinsicHeight();
- final boolean canBadgeInPlace = tryBadgeInPlace
- && (badgedDrawable instanceof BitmapDrawable)
- && ((BitmapDrawable) badgedDrawable).getBitmap().isMutable();
-
- final Bitmap bitmap;
- if (canBadgeInPlace) {
- bitmap = ((BitmapDrawable) badgedDrawable).getBitmap();
- } else {
- bitmap = Bitmap.createBitmap(badgedWidth, badgedHeight, Config.ARGB_8888);
- }
- Canvas canvas = new Canvas(bitmap);
-
- if (!canBadgeInPlace) {
- badgedDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
- badgedDrawable.draw(canvas);
- }
-
- if (badgeLocation != null) {
- if (badgeLocation.left < 0 || badgeLocation.top < 0
- || badgeLocation.width() > badgedWidth || badgeLocation.height() > badgedHeight) {
- throw new IllegalArgumentException("Badge location " + badgeLocation
- + " not in badged drawable bounds "
- + new Rect(0, 0, badgedWidth, badgedHeight));
- }
- badgeDrawable.setBounds(0, 0, badgeLocation.width(), badgeLocation.height());
-
- canvas.save();
- canvas.translate(badgeLocation.left, badgeLocation.top);
- badgeDrawable.draw(canvas);
- canvas.restore();
- } else {
- badgeDrawable.setBounds(0, 0, badgedWidth, badgedHeight);
- badgeDrawable.draw(canvas);
- }
-
- if (!canBadgeInPlace) {
- BitmapDrawable mergedDrawable = new BitmapDrawable(mContext.getResources(), bitmap);
-
- if (badgedDrawable instanceof BitmapDrawable) {
- BitmapDrawable bitmapDrawable = (BitmapDrawable) badgedDrawable;
- mergedDrawable.setTargetDensity(bitmapDrawable.getBitmap().getDensity());
- }
-
- return mergedDrawable;
- }
-
- return badgedDrawable;
+ return mContext.getPackageManager().getUserBadgedLabel(label, user);
}
/**
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 9361286..bf8ac65 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -535,7 +535,7 @@
destroyed = isDestroyedLocked();
}
- if (destroyed) {
+ if (destroyed && observer != null) {
try {
observer.onDestroy();
} catch (RemoteException re) {
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 0202f91..a5e86d8 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -116,8 +116,8 @@
* </pre>
* </p>
*/
- public static final String EXTRA_CALL_TYPE_FILTER
- = "android.provider.extra.call_type_filter";
+ public static final String EXTRA_CALL_TYPE_FILTER =
+ "android.provider.extra.CALL_TYPE_FILTER";
/**
* Content uri used to access call log entries, including voicemail records. You must have
@@ -167,8 +167,6 @@
*/
public static final String FEATURES = "features";
- /** Call had no associated features (e.g. voice-only). */
- public static final int FEATURES_NONE = 0x0;
/** Call had video. */
public static final int FEATURES_VIDEO = 0x1;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 27473e3..18a9eb1 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1125,7 +1125,7 @@
* import android.provider.ContactsContract.Contacts;
*
* Uri uri = Contacts.CONTENT_URI.buildUpon()
- * .appendQueryParameter(Contacts.ADDRESS_BOOK_INDEX_EXTRAS, "true")
+ * .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true")
* .build();
* Cursor cursor = getContentResolver().query(uri,
* new String[] {Contacts.DISPLAY_NAME},
@@ -1140,21 +1140,24 @@
* </pre>
* </p>
*/
- public static final String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX =
+ "android.provider.extra.ADDRESS_BOOK_INDEX";
/**
* The array of address book index titles, which are returned in the
* same order as the data in the cursor.
* <p>TYPE: String[]</p>
*/
- public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_TITLES =
+ "android.provider.extra.ADDRESS_BOOK_INDEX_TITLES";
/**
* The array of group counts for the corresponding group. Contains the same number
* of elements as the EXTRA_ADDRESS_BOOK_INDEX_TITLES array.
* <p>TYPE: int[]</p>
*/
- public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
+ public static final String EXTRA_ADDRESS_BOOK_INDEX_COUNTS =
+ "android.provider.extra.ADDRESS_BOOK_INDEX_COUNTS";
}
/**
@@ -8111,7 +8114,7 @@
* for the provided {@link Contacts} entry.
*/
public static final String ACTION_QUICK_CONTACT =
- "com.android.contacts.action.QUICK_CONTACT";
+ "android.provider.action.QUICK_CONTACT";
/**
* Extra used to specify pivot dialog location in screen coordinates.
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 8ca9b6c..e6bf6ba 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.StatusBarNotification;
import android.service.notification.NotificationRankingUpdate;
@@ -23,9 +24,9 @@
oneway interface INotificationListener
{
void onListenerConnected(in NotificationRankingUpdate update);
- void onNotificationPosted(in StatusBarNotification notification,
+ void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update);
- void onNotificationRemoved(in StatusBarNotification notification,
+ void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update);
void onNotificationRankingUpdate(in NotificationRankingUpdate update);
void onListenerHintsChanged(int hints);
diff --git a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
new file mode 100644
index 0000000..c25cdb2
--- /dev/null
+++ b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2014, 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.service.notification;
+
+import android.service.notification.StatusBarNotification;
+
+/** @hide */
+interface IStatusBarNotificationHolder {
+ /** Fetch the held StatusBarNotification. This method should only be called once per Holder */
+ StatusBarNotification get();
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index fc12101..d744070 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -602,8 +603,15 @@
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
- public void onNotificationPosted(StatusBarNotification sbn,
+ public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
+ StatusBarNotification sbn;
+ try {
+ sbn = sbnHolder.get();
+ } catch (RemoteException e) {
+ Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
+ return;
+ }
Notification.Builder.rebuild(getContext(), sbn.getNotification());
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
@@ -617,8 +625,15 @@
}
}
@Override
- public void onNotificationRemoved(StatusBarNotification sbn,
+ public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
+ StatusBarNotification sbn;
+ try {
+ sbn = sbnHolder.get();
+ } catch (RemoteException e) {
+ Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
+ return;
+ }
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
synchronized (mWrapper) {
applyUpdate(update);
@@ -693,10 +708,15 @@
* current {@link RankingMap}.
*/
public static class Ranking {
+ /** Value signifying that the user has not expressed a per-app visibility override value.
+ * @hide */
+ public static final int VISIBILITY_NO_OVERRIDE = -1000;
+
private String mKey;
private int mRank = -1;
private boolean mIsAmbient;
private boolean mMatchesInterruptionFilter;
+ private int mVisibilityOverride;
public Ranking() {}
@@ -726,6 +746,17 @@
}
/**
+ * Returns the user specificed visibility for the package that posted
+ * this notification, or
+ * {@link NotificationListenerService.Ranking#VISIBILITY_NO_OVERRIDE} if
+ * no such preference has been expressed.
+ * @hide
+ */
+ public int getVisibilityOverride() {
+ return mVisibilityOverride;
+ }
+
+ /**
* Returns whether the notification meets the user's interruption
* filter.
*
@@ -744,11 +775,12 @@
}
private void populate(String key, int rank, boolean isAmbient,
- boolean matchesInterruptionFilter) {
+ boolean matchesInterruptionFilter, int visibilityOverride) {
mKey = key;
mRank = rank;
mIsAmbient = isAmbient;
mMatchesInterruptionFilter = matchesInterruptionFilter;
+ mVisibilityOverride = visibilityOverride;
}
}
@@ -764,6 +796,7 @@
private final NotificationRankingUpdate mRankingUpdate;
private ArrayMap<String,Integer> mRanks;
private ArraySet<Object> mIntercepted;
+ private ArrayMap<String, Integer> mVisibilityOverrides;
private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
@@ -788,7 +821,8 @@
*/
public boolean getRanking(String key, Ranking outRanking) {
int rank = getRank(key);
- outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key));
+ outRanking.populate(key, rank, isAmbient(key), !isIntercepted(key),
+ getVisibilityOverride(key));
return rank >= 0;
}
@@ -820,6 +854,19 @@
return mIntercepted.contains(key);
}
+ private int getVisibilityOverride(String key) {
+ synchronized (this) {
+ if (mVisibilityOverrides == null) {
+ buildVisibilityOverridesLocked();
+ }
+ }
+ Integer overide = mVisibilityOverrides.get(key);
+ if (overide == null) {
+ return Ranking.VISIBILITY_NO_OVERRIDE;
+ }
+ return overide.intValue();
+ }
+
// Locked by 'this'
private void buildRanksLocked() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
@@ -837,6 +884,15 @@
Collections.addAll(mIntercepted, dndInterceptedKeys);
}
+ // Locked by 'this'
+ private void buildVisibilityOverridesLocked() {
+ Bundle visibilityBundle = mRankingUpdate.getVisibilityOverrides();
+ mVisibilityOverrides = new ArrayMap<>(visibilityBundle.size());
+ for (String key: visibilityBundle.keySet()) {
+ mVisibilityOverrides.put(key, visibilityBundle.getInt(key));
+ }
+ }
+
// ----------- Parcelable
@Override
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index 26af38b..6fba900 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -15,6 +15,7 @@
*/
package android.service.notification;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,18 +27,21 @@
private final String[] mKeys;
private final String[] mInterceptedKeys;
private final int mFirstAmbientIndex;
+ private final Bundle mVisibilityOverrides;
public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
- int firstAmbientIndex) {
+ Bundle visibilityOverrides, int firstAmbientIndex) {
mKeys = keys;
mFirstAmbientIndex = firstAmbientIndex;
mInterceptedKeys = interceptedKeys;
+ mVisibilityOverrides = visibilityOverrides;
}
public NotificationRankingUpdate(Parcel in) {
mKeys = in.readStringArray();
mFirstAmbientIndex = in.readInt();
mInterceptedKeys = in.readStringArray();
+ mVisibilityOverrides = in.readBundle();
}
@Override
@@ -50,6 +54,7 @@
out.writeStringArray(mKeys);
out.writeInt(mFirstAmbientIndex);
out.writeStringArray(mInterceptedKeys);
+ out.writeBundle(mVisibilityOverrides);
}
public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -74,4 +79,8 @@
public String[] getInterceptedKeys() {
return mInterceptedKeys;
}
+
+ public Bundle getVisibilityOverrides() {
+ return mVisibilityOverrides;
+ }
}
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 519bc28..8aa2689 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -450,7 +450,7 @@
* This intent must be invoked using {@link Activity#startActivityForResult(Intent, int)}.
* Starting re-enrollment is only valid if the keyphrase is un-enrolled,
* i.e. {@link #STATE_KEYPHRASE_UNENROLLED},
- * otherwise {@link #createIntentToReEnroll()} should be preferred.
+ * otherwise {@link #createReEnrollIntent()} should be preferred.
*
* @return An {@link Intent} to start enrollment for the given keyphrase.
* @throws UnsupportedOperationException if managing they keyphrase isn't supported.
@@ -460,8 +460,8 @@
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public Intent createIntentToEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToEnroll");
+ public Intent createEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createEnrollIntent");
synchronized (mLock) {
return getManageIntentLocked(MANAGE_ACTION_ENROLL);
}
@@ -481,8 +481,8 @@
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public Intent createIntentToUnEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToUnEnroll");
+ public Intent createUnEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createUnEnrollIntent");
synchronized (mLock) {
return getManageIntentLocked(MANAGE_ACTION_UN_ENROLL);
}
@@ -502,8 +502,8 @@
* This may happen if another detector has been instantiated or the
* {@link VoiceInteractionService} hosting this detector has been shut down.
*/
- public Intent createIntentToReEnroll() {
- if (DBG) Slog.d(TAG, "createIntentToReEnroll");
+ public Intent createReEnrollIntent() {
+ if (DBG) Slog.d(TAG, "createReEnrollIntent");
synchronized (mLock) {
return getManageIntentLocked(MANAGE_ACTION_RE_ENROLL);
}
diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
index faccde2..de527e9 100644
--- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
@@ -16,6 +16,7 @@
package android.service.wallpaper;
+import android.graphics.Rect;
import android.view.MotionEvent;
import android.os.Bundle;
@@ -24,6 +25,7 @@
*/
oneway interface IWallpaperEngine {
void setDesiredSize(int width, int height);
+ void setDisplayPadding(in Rect padding);
void setVisibility(boolean visible);
void dispatchPointer(in MotionEvent event);
void dispatchWallpaperCommand(String action, int x, int y,
diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl
index bc7a1d7..5fd0157 100644
--- a/core/java/android/service/wallpaper/IWallpaperService.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperService.aidl
@@ -16,6 +16,7 @@
package android.service.wallpaper;
+import android.graphics.Rect;
import android.service.wallpaper.IWallpaperConnection;
/**
@@ -24,5 +25,5 @@
oneway interface IWallpaperService {
void attach(IWallpaperConnection connection,
IBinder windowToken, int windowType, boolean isPreview,
- int reqWidth, int reqHeight);
+ int reqWidth, int reqHeight, in Rect padding);
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f3c26c8..26e9a30 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -16,6 +16,14 @@
package android.service.wallpaper;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import com.android.internal.R;
import com.android.internal.os.HandlerCaller;
import com.android.internal.view.BaseIWindow;
import com.android.internal.view.BaseSurfaceHolder;
@@ -56,6 +64,8 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+
/**
* A wallpaper service is responsible for showing a live wallpaper behind
* applications that would like to sit on top of it. This service object
@@ -90,7 +100,8 @@
private static final int DO_ATTACH = 10;
private static final int DO_DETACH = 20;
private static final int DO_SET_DESIRED_SIZE = 30;
-
+ private static final int DO_SET_DISPLAY_PADDING = 40;
+
private static final int MSG_UPDATE_SURFACE = 10000;
private static final int MSG_VISIBILITY_CHANGED = 10010;
private static final int MSG_WALLPAPER_OFFSETS = 10020;
@@ -150,13 +161,23 @@
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
int mCurWindowFlags = mWindowFlags;
int mCurWindowPrivateFlags = mWindowPrivateFlags;
+ TypedValue mOutsetBottom;
final Rect mVisibleInsets = new Rect();
final Rect mWinFrame = new Rect();
final Rect mOverscanInsets = new Rect();
final Rect mContentInsets = new Rect();
final Rect mStableInsets = new Rect();
+ final Rect mDispatchedOverscanInsets = new Rect();
+ final Rect mDispatchedContentInsets = new Rect();
+ final Rect mDispatchedStableInsets = new Rect();
+ final Rect mFinalSystemInsets = new Rect();
+ final Rect mFinalStableInsets = new Rect();
final Configuration mConfiguration = new Configuration();
-
+
+ private boolean mIsEmulator;
+ private boolean mIsCircularEmulator;
+ private boolean mWindowIsRound;
+
final WindowManager.LayoutParams mLayout
= new WindowManager.LayoutParams();
IWindowSession mSession;
@@ -406,7 +427,7 @@
*/
public void onCreate(SurfaceHolder surfaceHolder) {
}
-
+
/**
* Called right before the engine is going away. After this the
* surface will be destroyed and this Engine object is no longer
@@ -414,7 +435,7 @@
*/
public void onDestroy() {
}
-
+
/**
* Called to inform you of the wallpaper becoming visible or
* hidden. <em>It is very important that a wallpaper only use
@@ -422,7 +443,17 @@
*/
public void onVisibilityChanged(boolean visible) {
}
-
+
+ /**
+ * Called with the current insets that are in effect for the wallpaper.
+ * This gives you the part of the overall wallpaper surface that will
+ * generally be visible to the user (ignoring position offsets applied to it).
+ *
+ * @param insets Insets to apply.
+ */
+ public void onApplyWindowInsets(WindowInsets insets) {
+ }
+
/**
* Called as the user performs touch-screen interaction with the
* window that is currently showing this wallpaper. Note that the
@@ -432,7 +463,7 @@
*/
public void onTouchEvent(MotionEvent event) {
}
-
+
/**
* Called to inform you of the wallpaper's offsets changing
* within its contain, corresponding to the container's
@@ -443,7 +474,7 @@
float xOffsetStep, float yOffsetStep,
int xPixelOffset, int yPixelOffset) {
}
-
+
/**
* Process a command that was sent to the wallpaper with
* {@link WallpaperManager#sendWallpaperCommand}.
@@ -465,14 +496,14 @@
Bundle extras, boolean resultRequested) {
return null;
}
-
+
/**
* Called when an application has changed the desired virtual size of
* the wallpaper.
*/
public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
}
-
+
/**
* Convenience for {@link SurfaceHolder.Callback#surfaceChanged
* SurfaceHolder.Callback.surfaceChanged()}.
@@ -561,16 +592,20 @@
if (mDestroyed) {
Log.w(TAG, "Ignoring updateSurface: destroyed");
}
-
+
+ boolean fixedSize = false;
int myWidth = mSurfaceHolder.getRequestedWidth();
if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT;
+ else fixedSize = true;
int myHeight = mSurfaceHolder.getRequestedHeight();
if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT;
-
+ else fixedSize = true;
+
final boolean creating = !mCreated;
final boolean surfaceCreating = !mSurfaceCreated;
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
+ boolean insetsChanged = !mCreated;
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
final boolean flagsChanged = mCurWindowFlags != mWindowFlags ||
mCurWindowPrivateFlags != mWindowPrivateFlags;
@@ -607,6 +642,32 @@
mLayout.token = mWindowToken;
if (!mCreated) {
+ // Retrieve watch round and outset info
+ final WindowManager windowService = (WindowManager)getSystemService(
+ Context.WINDOW_SERVICE);
+ TypedArray windowStyle = obtainStyledAttributes(
+ com.android.internal.R.styleable.Window);
+ final Display display = windowService.getDefaultDisplay();
+ final boolean shouldUseBottomOutset =
+ display.getDisplayId() == Display.DEFAULT_DISPLAY;
+ if (shouldUseBottomOutset && windowStyle.hasValue(
+ R.styleable.Window_windowOutsetBottom)) {
+ if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
+ windowStyle.getValue(R.styleable.Window_windowOutsetBottom,
+ mOutsetBottom);
+ } else {
+ mOutsetBottom = null;
+ }
+ mWindowIsRound = getResources().getBoolean(
+ com.android.internal.R.bool.config_windowIsRound);
+ windowStyle.recycle();
+
+ // detect emulator
+ mIsEmulator = Build.HARDWARE.contains("goldfish");
+ mIsCircularEmulator = SystemProperties.getBoolean(
+ ViewRootImpl.PROPERTY_EMULATOR_CIRCULAR, false);
+
+ // Add window
mLayout.type = mIWallpaperEngine.mWindowType;
mLayout.gravity = Gravity.START|Gravity.TOP;
mLayout.setTitle(WallpaperService.this.getClass().getName());
@@ -627,6 +688,11 @@
mSurfaceHolder.mSurfaceLock.lock();
mDrawingAllowed = true;
+ if (!fixedSize) {
+ mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding);
+ } else {
+ mLayout.surfaceInsets.set(0, 0, 0, 0);
+ }
final int relayoutResult = mSession.relayout(
mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets,
@@ -636,16 +702,39 @@
+ ", frame=" + mWinFrame);
int w = mWinFrame.width();
+ int h = mWinFrame.height();
+
+ if (!fixedSize) {
+ final Rect padding = mIWallpaperEngine.mDisplayPadding;
+ w += padding.left + padding.right;
+ h += padding.top + padding.bottom;
+ mOverscanInsets.left += padding.left;
+ mOverscanInsets.top += padding.top;
+ mOverscanInsets.right += padding.right;
+ mOverscanInsets.bottom += padding.bottom;
+ mContentInsets.left += padding.left;
+ mContentInsets.top += padding.top;
+ mContentInsets.right += padding.right;
+ mContentInsets.bottom += padding.bottom;
+ mStableInsets.left += padding.left;
+ mStableInsets.top += padding.top;
+ mStableInsets.right += padding.right;
+ mStableInsets.bottom += padding.bottom;
+ }
+
if (mCurWidth != w) {
sizeChanged = true;
mCurWidth = w;
}
- int h = mWinFrame.height();
if (mCurHeight != h) {
sizeChanged = true;
mCurHeight = h;
}
+ insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets);
+ insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets);
+ insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets);
+
mSurfaceHolder.setSurfaceFrameSize(w, h);
mSurfaceHolder.mSurfaceLock.unlock();
@@ -702,6 +791,25 @@
}
}
+ if (insetsChanged) {
+ mDispatchedOverscanInsets.set(mOverscanInsets);
+ mDispatchedContentInsets.set(mContentInsets);
+ mDispatchedStableInsets.set(mStableInsets);
+ final boolean isRound = (mIsEmulator && mIsCircularEmulator)
+ || mWindowIsRound;
+ mFinalSystemInsets.set(mDispatchedOverscanInsets);
+ mFinalStableInsets.set(mDispatchedStableInsets);
+ if (mOutsetBottom != null) {
+ final DisplayMetrics metrics = getResources().getDisplayMetrics();
+ mFinalSystemInsets.bottom =
+ ( (int) mOutsetBottom.getDimension(metrics) )
+ + mIWallpaperEngine.mDisplayPadding.bottom;
+ }
+ WindowInsets insets = new WindowInsets(mFinalSystemInsets,
+ null, mFinalStableInsets, isRound);
+ onApplyWindowInsets(insets);
+ }
+
if (redrawNeeded) {
onSurfaceRedrawNeeded(mSurfaceHolder);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
@@ -781,7 +889,7 @@
mReportedVisible = false;
updateSurface(false, false, false);
}
-
+
void doDesiredSizeChanged(int desiredWidth, int desiredHeight) {
if (!mDestroyed) {
if (DEBUG) Log.v(TAG, "onDesiredSizeChanged("
@@ -792,14 +900,24 @@
doOffsetsChanged(true);
}
}
-
+
+ void doDisplayPaddingChanged(Rect padding) {
+ if (!mDestroyed) {
+ if (DEBUG) Log.v(TAG, "onDisplayPaddingChanged(" + padding + "): " + this);
+ if (!mIWallpaperEngine.mDisplayPadding.equals(padding)) {
+ mIWallpaperEngine.mDisplayPadding.set(padding);
+ updateSurface(true, false, false);
+ }
+ }
+ }
+
void doVisibilityChanged(boolean visible) {
if (!mDestroyed) {
mVisible = visible;
reportVisibility();
}
}
-
+
void reportVisibility() {
if (!mDestroyed) {
boolean visible = mVisible && mScreenOn;
@@ -956,12 +1074,13 @@
boolean mShownReported;
int mReqWidth;
int mReqHeight;
-
+ final Rect mDisplayPadding = new Rect();
+
Engine mEngine;
-
+
IWallpaperEngineWrapper(WallpaperService context,
IWallpaperConnection conn, IBinder windowToken,
- int windowType, boolean isPreview, int reqWidth, int reqHeight) {
+ int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) {
mCaller = new HandlerCaller(context, context.getMainLooper(), this, true);
mConnection = conn;
mWindowToken = windowToken;
@@ -969,16 +1088,22 @@
mIsPreview = isPreview;
mReqWidth = reqWidth;
mReqHeight = reqHeight;
+ mDisplayPadding.set(padding);
Message msg = mCaller.obtainMessage(DO_ATTACH);
mCaller.sendMessage(msg);
}
-
+
public void setDesiredSize(int width, int height) {
Message msg = mCaller.obtainMessageII(DO_SET_DESIRED_SIZE, width, height);
mCaller.sendMessage(msg);
}
-
+
+ public void setDisplayPadding(Rect padding) {
+ Message msg = mCaller.obtainMessageO(DO_SET_DISPLAY_PADDING, padding);
+ mCaller.sendMessage(msg);
+ }
+
public void setVisibility(boolean visible) {
Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
visible ? 1 : 0);
@@ -1041,6 +1166,9 @@
mEngine.doDesiredSizeChanged(message.arg1, message.arg2);
return;
}
+ case DO_SET_DISPLAY_PADDING: {
+ mEngine.doDisplayPaddingChanged((Rect) message.obj);
+ }
case MSG_UPDATE_SURFACE:
mEngine.updateSurface(true, false, false);
break;
@@ -1102,9 +1230,9 @@
@Override
public void attach(IWallpaperConnection conn, IBinder windowToken,
- int windowType, boolean isPreview, int reqWidth, int reqHeight) {
+ int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding) {
new IWallpaperEngineWrapper(mTarget, conn, windowToken,
- windowType, isPreview, reqWidth, reqHeight);
+ windowType, isPreview, reqWidth, reqHeight, padding);
}
}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 7245975..a4b6e92 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -578,7 +578,7 @@
*
* @deprecated Starting from API level 20, to select network synthesis, call
* ({@link TextToSpeech#getVoices()}, find a suitable network voice
- * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+ * ({@link Voice#isNetworkConnectionRequired()}) and pass it
* to {@link TextToSpeech#setVoice(Voice)}).
*/
@Deprecated
@@ -596,7 +596,7 @@
* @deprecated Starting from API level 20, to select embedded synthesis, call
* ({@link TextToSpeech#getVoices()}, find a suitable embedded voice
- * ({@link Voice#getRequiresNetworkConnection()}) and pass it
+ * ({@link Voice#isNetworkConnectionRequired()}) and pass it
* to {@link TextToSpeech#setVoice(Voice)}).
*/
@Deprecated
@@ -957,20 +957,18 @@
*
* @param text
* The string of text. Example: <code>"south_south_east"</code>
- * @param filename
- * The full path to the sound file (for example:
- * "/sdcard/mysounds/hello.wav")
+ * @param file
+ * File object pointing to the sound file.
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
*/
- public int addSpeech(CharSequence text, String filename) {
+ public int addSpeech(CharSequence text, File file) {
synchronized (mStartLock) {
- mUtterances.put(text, Uri.parse(filename));
+ mUtterances.put(text, Uri.fromFile(file));
return SUCCESS;
}
}
-
/**
* Adds a mapping between a string of text and a sound resource in a
* package. Use this to add custom earcons.
@@ -1017,7 +1015,11 @@
* "/sdcard/mysounds/tick.wav")
*
* @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+ *
+ * @deprecated As of API level 20, replaced by
+ * {@link #addEarcon(String, File)}.
*/
+ @Deprecated
public int addEarcon(String earcon, String filename) {
synchronized(mStartLock) {
mEarcons.put(earcon, Uri.parse(filename));
@@ -1025,6 +1027,27 @@
}
}
+ /**
+ * Adds a mapping between a string of text and a sound file.
+ * Use this to add custom earcons.
+ *
+ * @see #playEarcon(String, int, HashMap)
+ *
+ * @param earcon
+ * The name of the earcon.
+ * Example: <code>"[tick]"</code>
+ * @param file
+ * File object pointing to the sound file.
+ *
+ * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}.
+ */
+ public int addEarcon(String earcon, File file) {
+ synchronized(mStartLock) {
+ mEarcons.put(earcon, Uri.fromFile(file));
+ return SUCCESS;
+ }
+ }
+
private Uri makeResourceUri(String packageName, int resourceId) {
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
@@ -1061,7 +1084,7 @@
*/
public int speak(final CharSequence text,
final int queueMode,
- final HashMap<String, String> params,
+ final Bundle params,
final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
@@ -1103,11 +1126,11 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
* @deprecated As of API level 20, replaced by
- * {@link #speak(CharSequence, int, HashMap, String)}.
+ * {@link #speak(CharSequence, int, Bundle, String)}.
*/
@Deprecated
public int speak(final String text, final int queueMode, final HashMap<String, String> params) {
- return speak(text, queueMode, params,
+ return speak(text, queueMode, convertParamsHashMaptoBundle(params),
params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
@@ -1135,7 +1158,7 @@
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
*/
public int playEarcon(final String earcon, final int queueMode,
- final HashMap<String, String> params, final String utteranceId) {
+ final Bundle params, final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
@@ -1173,12 +1196,12 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
* @deprecated As of API level 20, replaced by
- * {@link #playEarcon(String, int, HashMap, String)}.
+ * {@link #playEarcon(String, int, Bundle, String)}.
*/
@Deprecated
public int playEarcon(final String earcon, final int queueMode,
final HashMap<String, String> params) {
- return playEarcon(earcon, queueMode, params,
+ return playEarcon(earcon, queueMode, convertParamsHashMaptoBundle(params),
params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
@@ -1757,22 +1780,20 @@
* must be prefixed by the name of the engine they are intended for. For example
* the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
* engine named "com.svox.pico" if it is being used.
- * @param filename Absolute file filename to write the generated audio data to.It should be
- * something like "/sdcard/myappsounds/mysound.wav".
+ * @param file File to write the generated audio data to.
* @param utteranceId An unique identifier for this request.
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
*/
- public int synthesizeToFile(final CharSequence text, final HashMap<String, String> params,
- final String filename, final String utteranceId) {
+ public int synthesizeToFile(final CharSequence text, final Bundle params,
+ final File file, final String utteranceId) {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
ParcelFileDescriptor fileDescriptor;
int returnValue;
try {
- File file = new File(filename);
if(file.exists() && !file.canWrite()) {
- Log.e(TAG, "Can't write to " + filename);
+ Log.e(TAG, "Can't write to " + file);
return ERROR;
}
fileDescriptor = ParcelFileDescriptor.open(file,
@@ -1784,10 +1805,10 @@
fileDescriptor.close();
return returnValue;
} catch (FileNotFoundException e) {
- Log.e(TAG, "Opening file " + filename + " failed", e);
+ Log.e(TAG, "Opening file " + file + " failed", e);
return ERROR;
} catch (IOException e) {
- Log.e(TAG, "Closing file " + filename + " failed", e);
+ Log.e(TAG, "Closing file " + file + " failed", e);
return ERROR;
}
}
@@ -1817,16 +1838,18 @@
*
* @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
* @deprecated As of API level 20, replaced by
- * {@link #synthesizeToFile(CharSequence, HashMap, String, String)}.
+ * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}.
*/
+ @Deprecated
public int synthesizeToFile(final String text, final HashMap<String, String> params,
final String filename) {
- return synthesizeToFile(text, params, filename, params.get(Engine.KEY_PARAM_UTTERANCE_ID));
+ return synthesizeToFile(text, convertParamsHashMaptoBundle(params),
+ new File(filename), params.get(Engine.KEY_PARAM_UTTERANCE_ID));
}
- private Bundle getParams(HashMap<String, String> params) {
+ private Bundle convertParamsHashMaptoBundle(HashMap<String, String> params) {
if (params != null && !params.isEmpty()) {
- Bundle bundle = new Bundle(mParams);
+ Bundle bundle = new Bundle();
copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM);
copyIntParam(bundle, params, Engine.KEY_PARAM_SESSION_ID);
copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID);
@@ -1852,11 +1875,85 @@
}
return bundle;
+ }
+ return null;
+ }
+
+ private Bundle getParams(Bundle params) {
+ if (params != null && !params.isEmpty()) {
+ Bundle bundle = new Bundle(mParams);
+ bundle.putAll(params);
+
+ verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_STREAM);
+ verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_SESSION_ID);
+ verifyStringBundleParam(bundle, Engine.KEY_PARAM_UTTERANCE_ID);
+ verifyFloatBundleParam(bundle, Engine.KEY_PARAM_VOLUME);
+ verifyFloatBundleParam(bundle, Engine.KEY_PARAM_PAN);
+
+ // Copy feature strings defined by the framework.
+ verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_SYNTHESIS);
+ verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
+ verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_TIMEOUT_MS);
+ verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_RETRIES_COUNT);
+
+ return bundle;
} else {
return mParams;
}
}
+ private static boolean verifyIntegerBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Integer ||
+ bundle.get(key) instanceof Long)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be an Integer or a Long");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean verifyStringBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof String)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a String");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean verifyBooleanBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Boolean ||
+ bundle.get(key) instanceof String)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a Boolean or String");
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ private static boolean verifyFloatBundleParam(Bundle bundle, String key) {
+ if (bundle.containsKey(key)) {
+ if (!(bundle.get(key) instanceof Float ||
+ bundle.get(key) instanceof Double)) {
+ bundle.remove(key);
+ Log.w(TAG, "Synthesis request paramter " + key + " containst value "
+ + " with invalid type. Should be a Float or a Double");
+ return false;
+ }
+ }
+ return true;
+ }
+
private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) {
String value = params.get(key);
if (value != null) {
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4fea109..d00a433 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -84,7 +84,7 @@
* the following methods:
* <ul>
* <li>{@link #onGetVoices()}</li>
- * <li>{@link #isValidVoiceName(String)}</li>
+ * <li>{@link #onIsValidVoiceName(String)}</li>
* <li>{@link #onLoadVoice(String)}</li>
* <li>{@link #onGetDefaultVoiceNameFor(String, String, String)}</li>
* </ul>
@@ -278,7 +278,7 @@
*
* @return A list of voices supported.
*/
- protected List<Voice> onGetVoices() {
+ public List<Voice> onGetVoices() {
// Enumerate all locales and check if they are available
ArrayList<Voice> voices = new ArrayList<Voice>();
for (Locale locale : Locale.getAvailableLocales()) {
@@ -335,7 +335,7 @@
}
Locale properLocale = TtsEngines.normalizeTTSLocale(iso3Locale);
String voiceName = properLocale.toLanguageTag();
- if (isValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
+ if (onIsValidVoiceName(voiceName) == TextToSpeech.SUCCESS) {
return voiceName;
} else {
return null;
@@ -357,7 +357,7 @@
* @param voiceName Name of the voice.
* @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
*/
- protected int onLoadVoice(String voiceName) {
+ public int onLoadVoice(String voiceName) {
Locale locale = Locale.forLanguageTag(voiceName);
if (locale == null) {
return TextToSpeech.ERROR;
@@ -388,7 +388,7 @@
* @param voiceName Name of the voice.
* @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}.
*/
- protected int isValidVoiceName(String voiceName) {
+ public int onIsValidVoiceName(String voiceName) {
Locale locale = Locale.forLanguageTag(voiceName);
if (locale == null) {
return TextToSpeech.ERROR;
@@ -1275,7 +1275,7 @@
if (!checkNonNull(voiceName)) {
return TextToSpeech.ERROR;
}
- int retVal = isValidVoiceName(voiceName);
+ int retVal = onIsValidVoiceName(voiceName);
if (retVal == TextToSpeech.SUCCESS) {
SpeechItem item = new LoadVoiceItem(caller, Binder.getCallingUid(),
diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java
index a97141c..a1fa51d 100644
--- a/core/java/android/speech/tts/Voice.java
+++ b/core/java/android/speech/tts/Voice.java
@@ -162,7 +162,7 @@
/**
* @return Does the Voice require a network connection to work.
*/
- public boolean getRequiresNetworkConnection() {
+ public boolean isNetworkConnectionRequired() {
return mRequiresNetworkConnection;
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 7dce348..2b53c48 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -727,10 +727,9 @@
int[] runs = dirs.mDirections;
int lineStart = getLineStart(line);
for (int i = 0; i < runs.length; i += 2) {
- int start = lineStart + (runs[i] & RUN_LENGTH_MASK);
- // No need to test the end as an offset after the last run should return the value
- // corresponding of the last run
- if (offset >= start) {
+ int start = lineStart + runs[i];
+ int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
+ if (offset >= start && offset < limit) {
int level = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
return ((level & 1) != 0);
}
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 679e2cc..3222dbf 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -116,7 +116,8 @@
/**
* Move the cursor to the buffer offset physically above the current
- * offset, or return false if the cursor is already on the top line.
+ * offset, to the beginning if it is on the top line but not at the
+ * start, or return false if the cursor is already on the top line.
*/
public static boolean moveUp(Spannable text, Layout layout) {
int start = getSelectionStart(text);
@@ -149,6 +150,9 @@
setSelection(text, move);
return true;
+ } else if (end != 0) {
+ setSelection(text, 0);
+ return true;
}
}
@@ -157,7 +161,9 @@
/**
* Move the cursor to the buffer offset physically below the current
- * offset, or return false if the cursor is already on the bottom line.
+ * offset, to the end of the buffer if it is on the bottom line but
+ * not at the end, or return false if the cursor is already at the
+ * end of the buffer.
*/
public static boolean moveDown(Spannable text, Layout layout) {
int start = getSelectionStart(text);
@@ -190,6 +196,9 @@
setSelection(text, move);
return true;
+ } else if (end != text.length()) {
+ setSelection(text, text.length());
+ return true;
}
}
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index a27063d..f95fb49 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -41,9 +41,9 @@
* {@code
* <changeBounds>
* <arcMotion android:minimumHorizontalAngle="15"
- * android:minimumVerticalAngle="0" android:maximumAngle="90"/>
- * </changeBounds>
- * }
+ * android:minimumVerticalAngle="0"
+ * android:maximumAngle="90"/>
+ * </changeBounds>}
* </pre>
*/
public class ArcMotion extends PathMotion {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index cb0a875..1b8d57c 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -99,6 +99,7 @@
* @return <code>true</code> when a changed parent should execute the transition
* inside the scene root's overlay or <code>false</code> if a parent change only
* affects the transform of the transitioning view.
+ * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
*/
public boolean getReparentWithOverlay() {
return mUseOverlay;
@@ -120,6 +121,7 @@
* @return <code>true</code> when a changed parent should execute the transition
* inside the scene root's overlay or <code>false</code> if a parent change only
* affects the transform of the transitioning view.
+ * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
*/
public void setReparentWithOverlay(boolean reparentWithOverlay) {
mUseOverlay = reparentWithOverlay;
@@ -132,6 +134,7 @@
* view will be tracked. Default is true.
*
* @return whether parent changes will be tracked by the ChangeTransform.
+ * @attr ref android.R.styleable#ChangeTransform_reparent
*/
public boolean getReparent() {
return mReparent;
@@ -145,6 +148,7 @@
*
* @param reparent Set to true to track parent changes or false to only track changes
* of the transitioning view without considering the parent change.
+ * @attr ref android.R.styleable#ChangeTransform_reparent
*/
public void setReparent(boolean reparent) {
mReparent = reparent;
diff --git a/core/java/android/transition/PatternMotion.java b/core/java/android/transition/PatternPathMotion.java
similarity index 68%
rename from core/java/android/transition/PatternMotion.java
rename to core/java/android/transition/PatternPathMotion.java
index e4045b4..a609df6 100644
--- a/core/java/android/transition/PatternMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -34,36 +34,35 @@
* <pre>
* {@code
* <changeBounds>
- * <patternMotion android:pathData="M0 0 L0 100 L100 100"/>
- * </changeBounds>
- * }
+ * <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * </changeBounds>}
* </pre>
*/
-public class PatternMotion extends PathMotion {
+public class PatternPathMotion extends PathMotion {
- private Path mOriginalPattern;
+ private Path mOriginalPatternPath;
- private final Path mPattern = new Path();
+ private final Path mPatternPath = new Path();
private final Matrix mTempMatrix = new Matrix();
/**
- * Constructs a PatternMotion with a straight-line pattern.
+ * Constructs a PatternPathMotion with a straight-line pattern.
*/
- public PatternMotion() {
- mPattern.lineTo(1, 0);
- mOriginalPattern = mPattern;
+ public PatternPathMotion() {
+ mPatternPath.lineTo(1, 0);
+ mOriginalPatternPath = mPatternPath;
}
- public PatternMotion(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternMotion);
+ public PatternPathMotion(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternPathMotion);
try {
- String pathData = a.getString(R.styleable.PatternMotion_pathData);
+ String pathData = a.getString(R.styleable.PatternPathMotion_patternPathData);
if (pathData == null) {
- throw new RuntimeException("pathData must be supplied for patternMotion");
+ throw new RuntimeException("pathData must be supplied for patternPathMotion");
}
Path pattern = PathParser.createPathFromPathData(pathData);
- setPattern(pattern);
+ setPatternPath(pattern);
} finally {
a.recycle();
}
@@ -71,14 +70,15 @@
}
/**
- * Creates a PatternMotion with the Path defining a pattern of motion between two coordinates.
- * The pattern will be translated, rotated, and scaled to fit between the start and end points.
- * The pattern must not be empty and must have the end point differ from the start point.
+ * Creates a PatternPathMotion with the Path defining a pattern of motion between two
+ * coordinates. The pattern will be translated, rotated, and scaled to fit between the start
+ * and end points. The pattern must not be empty and must have the end point differ from the
+ * start point.
*
- * @param pattern A Path to be used as a pattern for two-dimensional motion.
+ * @param patternPath A Path to be used as a pattern for two-dimensional motion.
*/
- public PatternMotion(Path pattern) {
- setPattern(pattern);
+ public PatternPathMotion(Path patternPath) {
+ setPatternPath(patternPath);
}
/**
@@ -87,10 +87,10 @@
* The pattern must not be empty and must have the end point differ from the start point.
*
* @return the Path defining a pattern of motion between two coordinates.
- * @attr ref android.R.styleable#PatternMotion_pathData
+ * @attr ref android.R.styleable#PatternPathMotion_patternPathData
*/
- public Path getPattern() {
- return mOriginalPattern;
+ public Path getPatternPath() {
+ return mOriginalPatternPath;
}
/**
@@ -98,11 +98,11 @@
* The pattern will be translated, rotated, and scaled to fit between the start and end points.
* The pattern must not be empty and must have the end point differ from the start point.
*
- * @param pattern A Path to be used as a pattern for two-dimensional motion.
- * @attr ref android.R.styleable#PatternMotion_pathData
+ * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+ * @attr ref android.R.styleable#PatternPathMotion_patternPathData
*/
- public void setPattern(Path pattern) {
- PathMeasure pathMeasure = new PathMeasure(pattern, false);
+ public void setPatternPath(Path patternPath) {
+ PathMeasure pathMeasure = new PathMeasure(patternPath, false);
float length = pathMeasure.getLength();
float[] pos = new float[2];
pathMeasure.getPosTan(length, pos, null);
@@ -124,8 +124,8 @@
mTempMatrix.postScale(scale, scale);
double angle = Math.atan2(dy, dx);
mTempMatrix.postRotate((float) Math.toDegrees(-angle));
- pattern.transform(mTempMatrix, mPattern);
- mOriginalPattern = pattern;
+ patternPath.transform(mTempMatrix, mPatternPath);
+ mOriginalPatternPath = patternPath;
}
@Override
@@ -139,7 +139,7 @@
mTempMatrix.postRotate((float) Math.toDegrees(angle));
mTempMatrix.postTranslate(startX, startY);
Path path = new Path();
- mPattern.transform(mTempMatrix, path);
+ mPatternPath.transform(mTempMatrix, path);
return path;
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index bd52e71..40bb6ec 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1417,9 +1417,9 @@
}
capturePropagationValues(values);
if (start) {
- addViewValues(mStartValues, view, values);
+ addViewValues(mStartValues, view, values, true);
} else {
- addViewValues(mEndValues, view, values);
+ addViewValues(mEndValues, view, values, true);
}
}
}
@@ -1460,7 +1460,7 @@
}
static void addViewValues(TransitionValuesMaps transitionValuesMaps,
- View view, TransitionValues transitionValues) {
+ View view, TransitionValues transitionValues, boolean setTransientState) {
transitionValuesMaps.viewValues.put(view, transitionValues);
int id = view.getId();
if (id >= 0) {
@@ -1489,11 +1489,15 @@
// Duplicate item IDs: cannot match by item ID.
View alreadyMatched = transitionValuesMaps.itemIdValues.get(itemId);
if (alreadyMatched != null) {
- alreadyMatched.setHasTransientState(false);
+ if (setTransientState) {
+ alreadyMatched.setHasTransientState(false);
+ }
transitionValuesMaps.itemIdValues.put(itemId, null);
}
} else {
- view.setHasTransientState(true);
+ if (setTransientState) {
+ view.setHasTransientState(true);
+ }
transitionValuesMaps.itemIdValues.put(itemId, view);
}
}
@@ -1560,9 +1564,9 @@
}
capturePropagationValues(values);
if (start) {
- addViewValues(mStartValues, view, values);
+ addViewValues(mStartValues, view, values, true);
} else {
- addViewValues(mEndValues, view, values);
+ addViewValues(mEndValues, view, values, true);
}
}
if (view instanceof ViewGroup) {
@@ -1989,8 +1993,33 @@
* by extending PathMotion and implementing
* {@link android.transition.PathMotion#getPath(float, float, float, float)}.
* </p>
+ * <p>
+ * When describing in XML, use a nested XML tag for the path motion. It can be one of
+ * the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+ * be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+ * attributed with the fully-described class name. For example:</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>
+ * }
+ * </pre>
+ * <p>or</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <arcMotion android:minimumHorizontalAngle="15"
+ * android:minimumVerticalAngle="0" android:maximumAngle="90"/>
+ * </changeBounds>
+ * }
+ * </pre>
+ *
* @param pathMotion Algorithm object to use for determining how to interpolate in two
* dimensions. If null, a straight-path algorithm will be used.
+ * @see android.transition.ArcMotion
+ * @see PatternPathMotion
+ * @see android.transition.PathMotion
*/
public void setPathMotion(PathMotion pathMotion) {
if (pathMotion == null) {
@@ -2004,7 +2033,31 @@
* Returns the algorithm object used to interpolate along two dimensions. This is typically
* used to determine the View motion between two points.
*
+ * <p>
+ * When describing in XML, use a nested XML tag for the path motion. It can be one of
+ * the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+ * be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+ * attributed with the fully-described class name. For example:</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>}
+ * </pre>
+ * <p>or</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <arcMotion android:minimumHorizontalAngle="15"
+ * android:minimumVerticalAngle="0"
+ * android:maximumAngle="90"/>
+ * </changeBounds>}
+ * </pre>
+ *
* @return The algorithm object used to interpolate along two dimensions.
+ * @see android.transition.ArcMotion
+ * @see PatternPathMotion
+ * @see android.transition.PathMotion
*/
public PathMotion getPathMotion() {
return mPathMotion;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 760ffe1..9009d6a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -171,8 +171,8 @@
parent.setPathMotion(new ArcMotion(mContext, attrs));
} else if ("pathMotion".equals(name)) {
parent.setPathMotion((PathMotion)createCustom(attrs, PathMotion.class, "pathMotion"));
- } else if ("patternMotion".equals(name)) {
- parent.setPathMotion(new PatternMotion(mContext, attrs));
+ } else if ("patternPathMotion".equals(name)) {
+ parent.setPathMotion(new PatternPathMotion(mContext, attrs));
} else {
throw new RuntimeException("Unknown scene name: " + parser.getName());
}
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index f6499ae..56db674 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -408,7 +408,7 @@
for (int i = 0; i < numValues; i++) {
View view = values.viewValues.keyAt(i);
if (isValidTarget(view)) {
- addViewValues(included, view, values.viewValues.valueAt(i));
+ addViewValues(included, view, values.viewValues.valueAt(i), false);
}
}
return included;
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 0b02552..d648ca6 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -358,12 +358,16 @@
overlayView = startView;
} else if (startView.getParent() instanceof View) {
View startParent = (View) startView.getParent();
- if (!isValidTarget(startParent)) {
- if (startView.isAttachedToWindow()) {
- overlayView = copyViewImage(startView);
- } else {
- overlayView = startView;
- }
+ VisibilityInfo parentVisibilityInfo = null;
+ TransitionValues endParentValues = getMatchedTransitionValues(startParent,
+ true);
+ if (endParentValues != null) {
+ TransitionValues startParentValues = getTransitionValues(startParent, true);
+ parentVisibilityInfo =
+ getVisibilityChangeInfo(startParentValues, endParentValues);
+ }
+ if (parentVisibilityInfo == null || !parentVisibilityInfo.visibilityChange) {
+ overlayView = copyViewImage(startView);
} else if (startParent.getParent() == null) {
int id = startParent.getId();
if (id != View.NO_ID && sceneRoot.findViewById(id) != null
diff --git a/core/java/android/util/Size.java b/core/java/android/util/Size.java
index 6424344..62df564 100644
--- a/core/java/android/util/Size.java
+++ b/core/java/android/util/Size.java
@@ -18,13 +18,10 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
/**
* Immutable class for describing width and height dimensions in pixels.
*/
-public final class Size implements Parcelable {
+public final class Size {
/**
* Create a new immutable Size instance.
*
@@ -36,11 +33,6 @@
mHeight = height;
}
- private Size(Parcel in) {
- mWidth = in.readInt();
- mHeight = in.readInt();
- }
-
/**
* Get the width of the size (in pixels).
* @return width
@@ -155,29 +147,6 @@
return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
}
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mWidth);
- out.writeInt(mHeight);
- }
-
- public static final Parcelable.Creator<Size> CREATOR = new Parcelable.Creator<Size>() {
- @Override
- public Size createFromParcel(Parcel in) {
- return new Size(in);
- }
-
- @Override
- public Size[] newArray(int size) {
- return new Size[size];
- }
- };
-
private final int mWidth;
private final int mHeight;
}
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
index 88bb4393..ac4f187 100644
--- a/core/java/android/util/SizeF.java
+++ b/core/java/android/util/SizeF.java
@@ -18,9 +18,6 @@
import static com.android.internal.util.Preconditions.checkArgumentFinite;
-import android.os.Parcel;
-import android.os.Parcelable;
-
/**
* Immutable class for describing width and height dimensions in some arbitrary
* unit.
@@ -28,7 +25,7 @@
* Width and height are finite values stored as a floating point representation.
* </p>
*/
-public final class SizeF implements Parcelable {
+public final class SizeF {
/**
* Create a new immutable SizeF instance.
*
@@ -46,11 +43,6 @@
mHeight = checkArgumentFinite(height, "height");
}
- private SizeF(Parcel in) {
- mWidth = in.readFloat();
- mHeight = in.readFloat();
- }
-
/**
* Get the width of the size (as an arbitrary unit).
* @return width
@@ -111,29 +103,6 @@
return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
}
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeFloat(mWidth);
- out.writeFloat(mHeight);
- }
-
- public static final Parcelable.Creator<SizeF> CREATOR = new Parcelable.Creator<SizeF>() {
- @Override
- public SizeF createFromParcel(Parcel in) {
- return new SizeF(in);
- }
-
- @Override
- public SizeF[] newArray(int size) {
- return new SizeF[size];
- }
- };
-
private final float mWidth;
private final float mHeight;
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index a10dda3..a283b91 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -19,7 +19,6 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -101,7 +100,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID;
message.arg1 = flags;
SomeArgs args = SomeArgs.obtain();
@@ -176,7 +175,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID;
message.arg1 = flags;
message.arg2 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
@@ -261,7 +260,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
long interrogatingTid, MagnificationSpec spec) {
Message message = mHandler.obtainMessage();
- message.what = PrivateHandler.MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
+ message.what = PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT;
message.arg1 = flags;
SomeArgs args = SomeArgs.obtain();
@@ -637,6 +636,95 @@
}
}
+ public void computeClickPointInScreenClientThread(long accessibilityNodeId,
+ Region interactiveRegion, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+ long interrogatingTid, MagnificationSpec spec) {
+ Message message = mHandler.obtainMessage();
+ message.what = PrivateHandler.MSG_COMPUTE_CLICK_POINT_IN_SCREEN;
+
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
+ args.argi2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
+ args.argi3 = interactionId;
+ args.arg1 = callback;
+ args.arg2 = spec;
+ args.arg3 = interactiveRegion;
+
+ message.obj = args;
+
+ // If the interrogation is performed by the same thread as the main UI
+ // thread in this process, set the message as a static reference so
+ // after this call completes the same thread but in the interrogating
+ // client can handle the message to generate the result.
+ if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId) {
+ AccessibilityInteractionClient.getInstanceForThread(
+ interrogatingTid).setSameThreadMessage(message);
+ } else {
+ mHandler.sendMessage(message);
+ }
+ }
+
+ private void computeClickPointInScreenUiThread(Message message) {
+ SomeArgs args = (SomeArgs) message.obj;
+ final int accessibilityViewId = args.argi1;
+ final int virtualDescendantId = args.argi2;
+ final int interactionId = args.argi3;
+ final IAccessibilityInteractionConnectionCallback callback =
+ (IAccessibilityInteractionConnectionCallback) args.arg1;
+ final MagnificationSpec spec = (MagnificationSpec) args.arg2;
+ final Region interactiveRegion = (Region) args.arg3;
+ args.recycle();
+
+ boolean succeeded = false;
+ Point point = mTempPoint;
+ try {
+ if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
+ return;
+ }
+ View target = null;
+ if (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ target = findViewByAccessibilityId(accessibilityViewId);
+ } else {
+ target = mViewRootImpl.mView;
+ }
+ if (target != null && isShown(target)) {
+ AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
+ if (provider != null) {
+ // For virtual views just use the center of the bounds in screen.
+ AccessibilityNodeInfo node = null;
+ if (virtualDescendantId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ node = provider.createAccessibilityNodeInfo(virtualDescendantId);
+ } else {
+ node = provider.createAccessibilityNodeInfo(
+ AccessibilityNodeProvider.HOST_VIEW_ID);
+ }
+ if (node != null) {
+ succeeded = true;
+ Rect boundsInScreen = mTempRect;
+ node.getBoundsInScreen(boundsInScreen);
+ point.set(boundsInScreen.centerX(), boundsInScreen.centerY());
+ }
+ } else if (virtualDescendantId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
+ // For a real view, ask the view to compute the click point.
+ succeeded = target.computeClickPointInScreenForAccessibility(
+ interactiveRegion, point);
+ }
+ }
+ } finally {
+ try {
+ Point result = null;
+ if (succeeded) {
+ applyAppScaleAndMagnificationSpecIfNeeded(point, spec);
+ result = point;
+ }
+ callback.setComputeClickPointInScreenActionResult(result, interactionId);
+ } catch (RemoteException re) {
+ /* ignore - the other side will time out */
+ }
+ }
+ }
+
private View findViewByAccessibilityId(int accessibilityId) {
View root = mViewRootImpl.mView;
if (root == null) {
@@ -688,6 +776,26 @@
}
}
+ private void applyAppScaleAndMagnificationSpecIfNeeded(Point point,
+ MagnificationSpec spec) {
+ final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+ if (!shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
+ return;
+ }
+
+ if (applicationScale != 1.0f) {
+ point.x *= applicationScale;
+ point.y *= applicationScale;
+ }
+
+ if (spec != null) {
+ point.x *= spec.scale;
+ point.y *= spec.scale;
+ point.x += (int) spec.offsetX;
+ point.y += (int) spec.offsetY;
+ }
+ }
+
private void applyAppScaleAndMagnificationSpecIfNeeded(AccessibilityNodeInfo info,
MagnificationSpec spec) {
if (info == null) {
@@ -1080,11 +1188,12 @@
private class PrivateHandler extends Handler {
private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 1;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID = 3;
- private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 4;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID = 2;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID = 3;
+ private final static int MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT = 4;
private final static int MSG_FIND_FOCUS = 5;
private final static int MSG_FOCUS_SEARCH = 6;
+ private final static int MSG_COMPUTE_CLICK_POINT_IN_SCREEN = 7;
public PrivateHandler(Looper looper) {
super(looper);
@@ -1096,16 +1205,18 @@
switch (type) {
case MSG_PERFORM_ACCESSIBILITY_ACTION:
return "MSG_PERFORM_ACCESSIBILITY_ACTION";
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
- case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID";
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT:
- return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID";
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT:
+ return "MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT";
case MSG_FIND_FOCUS:
return "MSG_FIND_FOCUS";
case MSG_FOCUS_SEARCH:
return "MSG_FOCUS_SEARCH";
+ case MSG_COMPUTE_CLICK_POINT_IN_SCREEN:
+ return "MSG_COMPUTE_CLICK_POINT_IN_SCREEN";
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
@@ -1115,16 +1226,16 @@
public void handleMessage(Message message) {
final int type = message.what;
switch (type) {
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
findAccessibilityNodeInfoByAccessibilityIdUiThread(message);
} break;
case MSG_PERFORM_ACCESSIBILITY_ACTION: {
perfromAccessibilityActionUiThread(message);
} break;
- case MSG_FIND_ACCESSIBLITY_NODE_INFOS_BY_VIEW_ID: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFOS_BY_VIEW_ID: {
findAccessibilityNodeInfosByViewIdUiThread(message);
} break;
- case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT: {
+ case MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_TEXT: {
findAccessibilityNodeInfosByTextUiThread(message);
} break;
case MSG_FIND_FOCUS: {
@@ -1133,6 +1244,9 @@
case MSG_FOCUS_SEARCH: {
focusSearchUiThread(message);
} break;
+ case MSG_COMPUTE_CLICK_POINT_IN_SCREEN: {
+ computeClickPointInScreenUiThread(message);
+ } break;
default:
throw new IllegalArgumentException("Unknown message type: " + type);
}
diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java
index 541b336..b3ac1db 100644
--- a/core/java/android/view/FrameStats.java
+++ b/core/java/android/view/FrameStats.java
@@ -28,7 +28,10 @@
*/
public static final long UNDEFINED_TIME_NANO = -1;
+ /** @hide */
protected long mRefreshPeriodNano;
+
+ /** @hide */
protected long[] mFramesPresentedTimeNano;
/**
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ceea9f8..076f1e2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -800,28 +800,6 @@
}
@Override
- public void drawPicture(Picture picture, Rect dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- @Override
- public void drawPicture(Picture picture, RectF dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- @Override
public void drawPoint(float x, float y, Paint paint) {
float[] point = getPointStorage();
point[0] = x;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5d6d998..6aa86c7 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -94,7 +94,8 @@
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp);
void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp);
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 0f3f182..037ed28 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -177,6 +177,11 @@
void wallpaperOffsetsComplete(IBinder window);
+ /**
+ * Apply a raw offset to the wallpaper service when shown behind this window.
+ */
+ void setWallpaperDisplayOffset(IBinder windowToken, int x, int y);
+
Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, in Bundle extras, boolean sync);
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 9dc9766..47f72a8 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -367,6 +367,10 @@
throw new IllegalArgumentException("Unrecognized outline?");
}
+ public boolean hasShadow() {
+ return nHasShadow(mNativeRenderNode);
+ }
+
/**
* Enables or disables clipping to the outline.
*
@@ -861,6 +865,7 @@
float alpha);
private static native boolean nSetOutlineEmpty(long renderNode);
private static native boolean nSetOutlineNone(long renderNode);
+ private static native boolean nHasShadow(long renderNode);
private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
private static native boolean nSetRevealClip(long renderNode,
boolean shouldClip, float x, float y, float radius);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index fa4a13a..debf45d 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -453,6 +453,12 @@
throw new IllegalStateException("Cannot clone this animator");
}
+ @Override
+ public void setAllowRunningAsynchronously(boolean mayRunAsync) {
+ checkMutable();
+ nSetAllowRunningAsync(mNativePtr.get(), mayRunAsync);
+ }
+
private static native long nCreateAnimator(int property, float finalValue);
private static native long nCreateCanvasPropertyFloatAnimator(
long canvasProperty, float finalValue);
@@ -466,6 +472,7 @@
private static native long nGetDuration(long nativePtr);
private static native void nSetStartDelay(long nativePtr, long startDelay);
private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
+ private static native void nSetAllowRunningAsync(long animPtr, boolean mayRunAsync);
private static native void nStart(long animPtr, RenderNodeAnimator finishListener);
private static native void nEnd(long animPtr);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1e28e33..4074529 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -39,7 +39,7 @@
private static native Bitmap nativeScreenshot(IBinder displayToken,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform);
+ boolean allLayers, boolean useIdentityTransform, int rotation);
private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
boolean allLayers, boolean useIdentityTransform);
@@ -688,17 +688,23 @@
* @param useIdentityTransform Replace whatever transformation (rotation,
* scaling, translation) the surface layers are currently using with the
* identity transformation while taking the screenshot.
+ * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
+ * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
+ * screenshots in its native portrait orientation by default, so this is
+ * useful for returning screenshots that are independent of device
+ * orientation.
* @return Returns a Bitmap containing the screen contents, or null
* if an error occurs. Make sure to call Bitmap.recycle() as soon as
* possible, once its content is not needed anymore.
*/
public static Bitmap screenshot(Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform) {
+ int minLayer, int maxLayer, boolean useIdentityTransform,
+ int rotation) {
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
return nativeScreenshot(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, false, useIdentityTransform);
+ minLayer, maxLayer, false, useIdentityTransform, rotation);
}
/**
@@ -717,7 +723,8 @@
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
- return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true, false);
+ return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
+ false, Surface.ROTATION_0);
}
private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 21e7c6b..82c5425 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -35,6 +35,8 @@
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -444,16 +446,19 @@
* <a name="Drawing"></a>
* <h3>Drawing</h3>
* <p>
- * Drawing is handled by walking the tree and rendering each view that
- * intersects the invalid region. Because the tree is traversed in-order,
- * this means that parents will draw before (i.e., behind) their children, with
- * siblings drawn in the order they appear in the tree.
- * If you set a background drawable for a View, then the View will draw it for you
- * before calling back to its <code>onDraw()</code> method.
+ * Drawing is handled by walking the tree and recording the drawing commands of
+ * any View that needs to update. After this, the drawing commands of the
+ * entire tree are issued to screen, clipped to the newly damaged area.
* </p>
*
* <p>
- * Note that the framework will not draw views that are not in the invalid region.
+ * The tree is largely recorded and drawn in order, with parents drawn before
+ * (i.e., behind) their children, with siblings drawn in the order they appear
+ * in the tree. If you set a background drawable for a View, then the View will
+ * draw it before calling back to its <code>onDraw()</code> method. The child
+ * drawing order can be overridden with
+ * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
+ * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
* </p>
*
* <p>
@@ -5728,6 +5733,136 @@
}
/**
+ * Computes a point on which a sequence of a down/up event can be sent to
+ * trigger clicking this view. This method is for the exclusive use by the
+ * accessibility layer to determine where to send a click event in explore
+ * by touch mode.
+ *
+ * @param interactiveRegion The interactive portion of this window.
+ * @param outPoint The point to populate.
+ * @return True of such a point exists.
+ */
+ boolean computeClickPointInScreenForAccessibility(Region interactiveRegion,
+ Point outPoint) {
+ // Since the interactive portion of the view is a region but as a view
+ // may have a transformation matrix which cannot be applied to a
+ // region we compute the view bounds rectangle and all interactive
+ // predecessor's and sibling's (siblings of predecessors included)
+ // rectangles that intersect the view bounds. At the
+ // end if the view was partially covered by another interactive
+ // view we compute the view's interactive region and pick a point
+ // on its boundary path as regions do not offer APIs to get inner
+ // points. Note that the the code is optimized to fail early and
+ // avoid unnecessary allocations plus computations.
+
+ // The current approach has edge cases that may produce false
+ // positives or false negatives. For example, a portion of the
+ // view may be covered by an interactive descendant of a
+ // predecessor, which we do not compute. Also a view may be handling
+ // raw touch events instead registering click listeners, which
+ // we cannot compute. Despite these limitations this approach will
+ // work most of the time and it is a huge improvement over just
+ // blindly sending the down and up events in the center of the
+ // view.
+
+ // Cannot click on an unattached view.
+ if (mAttachInfo == null) {
+ return false;
+ }
+
+ // Attached to an invisible window means this view is not visible.
+ if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
+ return false;
+ }
+
+ RectF bounds = mAttachInfo.mTmpTransformRect;
+ bounds.set(0, 0, getWidth(), getHeight());
+ List<RectF> intersections = mAttachInfo.mTmpRectList;
+ intersections.clear();
+
+ if (mParent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) mParent;
+ if (!parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+ this, bounds, intersections)) {
+ intersections.clear();
+ return false;
+ }
+ }
+
+ // Take into account the window location.
+ final int dx = mAttachInfo.mWindowLeft;
+ final int dy = mAttachInfo.mWindowTop;
+ bounds.offset(dx, dy);
+ offsetRects(intersections, dx, dy);
+
+ if (intersections.isEmpty() && interactiveRegion == null) {
+ outPoint.set((int) bounds.centerX(), (int) bounds.centerY());
+ } else {
+ // This view is partially covered by other views, then compute
+ // the not covered region and pick a point on its boundary.
+ Region region = new Region();
+ region.set((int) bounds.left, (int) bounds.top,
+ (int) bounds.right, (int) bounds.bottom);
+
+ final int intersectionCount = intersections.size();
+ for (int i = intersectionCount - 1; i >= 0; i--) {
+ RectF intersection = intersections.remove(i);
+ region.op((int) intersection.left, (int) intersection.top,
+ (int) intersection.right, (int) intersection.bottom,
+ Region.Op.DIFFERENCE);
+ }
+
+ // If the view is completely covered, done.
+ if (region.isEmpty()) {
+ return false;
+ }
+
+ // Take into account the interactive portion of the window
+ // as the rest is covered by other windows. If no such a region
+ // then the whole window is interactive.
+ if (interactiveRegion != null) {
+ region.op(interactiveRegion, Region.Op.INTERSECT);
+ }
+
+ // If the view is completely covered, done.
+ if (region.isEmpty()) {
+ return false;
+ }
+
+ // Try a shortcut here.
+ if (region.isRect()) {
+ Rect regionBounds = mAttachInfo.mTmpInvalRect;
+ region.getBounds(regionBounds);
+ outPoint.set(regionBounds.centerX(), regionBounds.centerY());
+ return true;
+ }
+
+ // Get the a point on the region boundary path.
+ Path path = region.getBoundaryPath();
+ PathMeasure pathMeasure = new PathMeasure(path, false);
+ final float[] coordinates = mAttachInfo.mTmpTransformLocation;
+
+ // Without loss of generality pick a point.
+ final float point = pathMeasure.getLength() * 0.01f;
+ if (!pathMeasure.getPosTan(point, coordinates, null)) {
+ return false;
+ }
+
+ outPoint.set(Math.round(coordinates[0]), Math.round(coordinates[1]));
+ }
+
+ return true;
+ }
+
+ static void offsetRects(List<RectF> rects, float offsetX, float offsetY) {
+ final int rectCount = rects.size();
+ for (int i = 0; i < rectCount; i++) {
+ RectF intersection = rects.get(i);
+ intersection.offset(offsetX, offsetY);
+ }
+ }
+
+ /**
* Returns the delegate for implementing accessibility support via
* composition. For more details see {@link AccessibilityDelegate}.
*
@@ -10221,6 +10356,7 @@
*
* @return true if the content in this view might overlap, false otherwise.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean hasOverlappingRendering() {
return true;
}
@@ -10825,6 +10961,12 @@
/**
* Sets whether the View's Outline should be used to clip the contents of the View.
* <p>
+ * Only a single non-rectangular clip can be applied on a View at any time.
+ * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
+ * circular reveal} animation take priority over Outline clipping, and
+ * child Outline clipping takes priority over Outline clipping done by a
+ * parent.
+ * <p>
* Note that this flag will only be respected if the View's Outline returns true from
* {@link Outline#canClip()}.
*
@@ -10917,6 +11059,17 @@
invalidateViewProperty(false, false);
}
+ /**
+ * HierarchyViewer only
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean hasShadow() {
+ return mRenderNode.hasShadow();
+ }
+
+
/** @hide */
public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
mRenderNode.setRevealClip(shouldClip, x, y, radius);
@@ -15091,10 +15244,12 @@
bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
}
+ canvas.save();
canvas.translate(mScrollX, mScrollY);
+ canvas.clipRect(bounds, Region.Op.REPLACE);
drawable.setBounds(bounds);
drawable.draw(canvas);
- canvas.translate(-mScrollX, -mScrollY);
+ canvas.restore();
}
/**
@@ -20131,6 +20286,16 @@
final RectF mTmpTransformRect = new RectF();
/**
+ * Temporary for use in computing hit areas with transformed views
+ */
+ final RectF mTmpTransformRect1 = new RectF();
+
+ /**
+ * Temporary list of rectanges.
+ */
+ final List<RectF> mTmpRectList = new ArrayList<>();
+
+ /**
* Temporary for use in transforming invalidation rect
*/
final Matrix mTmpMatrix = new Matrix();
diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java
index 7ced088..001cd01 100644
--- a/core/java/android/view/ViewAnimationUtils.java
+++ b/core/java/android/view/ViewAnimationUtils.java
@@ -27,9 +27,13 @@
private ViewAnimationUtils() {}
/**
* Returns an Animator which can animate a clipping circle.
- *
+ * <p>
* Any shadow cast by the View will respect the circular clip from this animator.
- *
+ * <p>
+ * Only a single non-rectangular clip can be applied on a View at any time.
+ * Views clipped by a circular reveal animation take priority over
+ * {@link View#setClipToOutline(boolean) View Outline clipping}.
+ * <p>
* Note that the animation returned here is a one-shot animation. It cannot
* be re-used, and once started it cannot be paused or resumed.
*
@@ -39,7 +43,7 @@
* @param startRadius The starting radius of the animating circle.
* @param endRadius The ending radius of the animating circle.
*/
- public static final Animator createCircularReveal(View view,
+ public static Animator createCircularReveal(View view,
int centerX, int centerY, float startRadius, float endRadius) {
return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 6c66eb0..a94f973 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -26,6 +26,7 @@
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.TypedValue;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
@@ -315,6 +316,7 @@
private static final String REMOTE_COMMAND_CAPTURE = "CAPTURE";
private static final String REMOTE_COMMAND_DUMP = "DUMP";
+ private static final String REMOTE_COMMAND_DUMP_THEME = "DUMP_THEME";
private static final String REMOTE_COMMAND_INVALIDATE = "INVALIDATE";
private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT";
private static final String REMOTE_PROFILE = "PROFILE";
@@ -430,6 +432,8 @@
if (REMOTE_COMMAND_DUMP.equalsIgnoreCase(command)) {
dump(view, false, true, clientStream);
+ } else if (REMOTE_COMMAND_DUMP_THEME.equalsIgnoreCase(command)) {
+ dumpTheme(view, clientStream);
} else if (REMOTE_COMMAND_CAPTURE_LAYERS.equalsIgnoreCase(command)) {
captureLayers(view, new DataOutputStream(clientStream));
} else {
@@ -820,6 +824,64 @@
}
}
+ /**
+ * Dumps the theme attributes from the given View.
+ * @hide
+ */
+ public static void dumpTheme(View view, OutputStream clientStream) throws IOException {
+ BufferedWriter out = null;
+ try {
+ out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024);
+ String[] attributes = getStyleAttributesDump(view.getContext().getResources(),
+ view.getContext().getTheme());
+ if (attributes != null) {
+ for (int i = 0; i < attributes.length; i += 2) {
+ if (attributes[i] != null) {
+ out.write(attributes[i] + "\n");
+ out.write(attributes[i + 1] + "\n");
+ }
+ }
+ }
+ out.write("DONE.");
+ out.newLine();
+ } catch (Exception e) {
+ android.util.Log.w("View", "Problem dumping View Theme:", e);
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ }
+
+ /**
+ * Gets the style attributes from the {@link Resources.Theme}. For debugging only.
+ *
+ * @param resources Resources to resolve attributes from.
+ * @param theme Theme to dump.
+ * @return a String array containing pairs of adjacent Theme attribute data: name followed by
+ * its value.
+ *
+ * @hide
+ */
+ private static String[] getStyleAttributesDump(Resources resources, Resources.Theme theme) {
+ TypedValue outValue = new TypedValue();
+ String nullString = "null";
+ int i = 0;
+ int[] attributes = theme.getAllAttributes();
+ String[] data = new String[attributes.length * 2];
+ for (int attributeId : attributes) {
+ try {
+ data[i] = resources.getResourceName(attributeId);
+ data[i + 1] = theme.resolveAttribute(attributeId, outValue, true) ?
+ outValue.coerceToString().toString() : nullString;
+ i += 2;
+ } catch (Resources.NotFoundException e) {
+ // ignore resources we can't resolve
+ }
+ }
+ return data;
+ }
+
private static View findView(ViewGroup group, String className, int hashCode) {
if (isRequestedView(group, className, hashCode)) {
return group;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index adad082..4e1db90 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -771,6 +771,112 @@
}
/**
+ * Translates the given bounds and intersections from child coordinates to
+ * local coordinates. In case any interactive sibling of the calling child
+ * covers the latter, a new intersections is added to the intersection list.
+ * This method is for the exclusive use by the accessibility layer to compute
+ * a point where a sequence of down and up events would click on a view.
+ *
+ * @param child The child making the call.
+ * @param bounds The bounds to translate in child coordinates.
+ * @param intersections The intersections of interactive views covering the child.
+ * @return True if the bounds and intersections were computed, false otherwise.
+ */
+ boolean translateBoundsAndIntersectionsInWindowCoordinates(View child,
+ RectF bounds, List<RectF> intersections) {
+ // Not attached, done.
+ if (mAttachInfo == null) {
+ return false;
+ }
+
+ if (getAlpha() <= 0 || getTransitionAlpha() <= 0 ||
+ getVisibility() != VISIBLE) {
+ // Cannot click on a view with an invisible predecessor.
+ return false;
+ }
+
+ // Compensate for the child transformation.
+ if (!child.hasIdentityMatrix()) {
+ Matrix matrix = child.getMatrix();
+ matrix.mapRect(bounds);
+ final int intersectionCount = intersections.size();
+ for (int i = 0; i < intersectionCount; i++) {
+ RectF intersection = intersections.get(i);
+ matrix.mapRect(intersection);
+ }
+ }
+
+ // Translate the bounds from child to parent coordinates.
+ final int dx = child.mLeft - mScrollX;
+ final int dy = child.mTop - mScrollY;
+ bounds.offset(dx, dy);
+ offsetRects(intersections, dx, dy);
+
+ // If the bounds do not intersect our bounds, done.
+ if (!bounds.intersects(0, 0, getWidth(), getHeight())) {
+ return false;
+ }
+
+ // Check whether any clickable siblings cover the child
+ // view and if so keep track of the intersections. Also
+ // respect Z ordering when iterating over children.
+ ArrayList<View> orderedList = buildOrderedChildList();
+ final boolean useCustomOrder = orderedList == null
+ && isChildrenDrawingOrderEnabled();
+
+ final int childCount = mChildrenCount;
+ for (int i = childCount - 1; i >= 0; i--) {
+ final int childIndex = useCustomOrder
+ ? getChildDrawingOrder(childCount, i) : i;
+ final View sibling = (orderedList == null)
+ ? mChildren[childIndex] : orderedList.get(childIndex);
+
+ // We care only about siblings over the child.
+ if (sibling == child) {
+ break;
+ }
+
+ // If sibling is not interactive we do not care.
+ if (!sibling.isClickable() && !sibling.isLongClickable()) {
+ continue;
+ }
+
+ // Compute the sibling bounds in its coordinates.
+ RectF siblingBounds = mAttachInfo.mTmpTransformRect1;
+ siblingBounds.set(0, 0, sibling.getWidth(), sibling.getHeight());
+
+ // Take into account the sibling transformation matrix.
+ if (!sibling.hasIdentityMatrix()) {
+ sibling.getMatrix().mapRect(siblingBounds);
+ }
+
+ // Offset the sibling to our coordinates.
+ final int siblingDx = sibling.mLeft - mScrollX;
+ final int siblingDy = sibling.mTop - mScrollY;
+ siblingBounds.offset(siblingDx, siblingDy);
+
+ // Compute the intersection between the child and the sibling.
+ if (siblingBounds.intersect(bounds)) {
+ // If an interactive sibling completely covers the child, done.
+ if (siblingBounds.equals(bounds)) {
+ return false;
+ }
+ // Keep track of the intersection rectangle.
+ RectF intersection = new RectF(siblingBounds);
+ intersections.add(intersection);
+ }
+ }
+
+ if (mParent instanceof ViewGroup) {
+ ViewGroup parentGroup = (ViewGroup) mParent;
+ return parentGroup.translateBoundsAndIntersectionsInWindowCoordinates(
+ this, bounds, intersections);
+ }
+
+ return true;
+ }
+
+ /**
* Called when a child view has changed whether or not it is tracking transient state.
*/
public void childHasTransientStateChanged(View child, boolean childHasTransientState) {
@@ -3301,6 +3407,7 @@
* @return True if the group's children will be clipped to their bounds,
* false otherwise.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean getClipChildren() {
return ((mGroupFlags & FLAG_CLIP_CHILDREN) != 0);
}
@@ -3349,6 +3456,7 @@
*
* @attr ref android.R.styleable#ViewGroup_clipToPadding
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean getClipToPadding() {
return hasBooleanFlag(FLAG_CLIP_TO_PADDING);
}
@@ -5034,6 +5142,9 @@
/**
* Tells the ViewGroup whether to draw its children in the order defined by the method
* {@link #getChildDrawingOrder(int, int)}.
+ * <p>
+ * Note that {@link View#getZ() Z} reordering, done by {@link #dispatchDraw(Canvas)},
+ * will override custom child ordering done via this method.
*
* @param enabled true if the order of the children when drawing is determined by
* {@link #getChildDrawingOrder(int, int)}, false otherwise
@@ -5719,6 +5830,28 @@
}
@Override
+ public void drawableHotspotChanged(float x, float y) {
+ super.drawableHotspotChanged(x, y);
+
+ if ((mGroupFlags & FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE) != 0) {
+ if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) != 0) {
+ throw new IllegalStateException("addStateFromChildren cannot be enabled if a"
+ + " child has duplicateParentState set to true");
+ }
+
+ final View[] children = mChildren;
+ final int count = mChildrenCount;
+
+ for (int i = 0; i < count; i++) {
+ final View child = children[i];
+ if ((child.mViewFlags & DUPLICATE_PARENT_STATE) != 0) {
+ child.drawableHotspotChanged(x, y);
+ }
+ }
+ }
+ }
+
+ @Override
protected int[] onCreateDrawableState(int extraSpace) {
if ((mGroupFlags & FLAG_ADD_STATES_FROM_CHILDREN) == 0) {
return super.onCreateDrawableState(extraSpace);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1cbc9..43ab4ef 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -121,7 +121,7 @@
private static final String PROPERTY_MEDIA_DISABLED = "config.disable_media";
// property used by emulator to determine display shape
- private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+ public static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
/**
* Maximum time we allow the user to roll the trackball enough to generate
@@ -6111,6 +6111,33 @@
}
}
} break;
+
+
+ case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
+ if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView != null) {
+ // We care only for changes rooted in the focused host.
+ final long eventSourceId = event.getSourceNodeId();
+ final int hostViewId = AccessibilityNodeInfo.getAccessibilityViewId(
+ eventSourceId);
+ if (hostViewId != mAccessibilityFocusedHost.getAccessibilityViewId()) {
+ break;
+ }
+
+ // We only care about changes that may change the virtual focused view bounds.
+ final int changes = event.getContentChangeTypes();
+ if ((changes & AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) != 0
+ || changes == AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED) {
+ AccessibilityNodeProvider provider = mAccessibilityFocusedHost
+ .getAccessibilityNodeProvider();
+ if (provider != null) {
+ final int virtualChildId = AccessibilityNodeInfo.getVirtualDescendantId(
+ mAccessibilityFocusedVirtualView.getSourceNodeId());
+ mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(
+ virtualChildId);
+ }
+ }
+ }
+ } break;
}
mAccessibilityManager.sendAccessibilityEvent(event);
return true;
@@ -6652,12 +6679,12 @@
public void performAccessibilityAction(long accessibilityNodeId, int action,
Bundle arguments, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
- int interogatingPid, long interrogatingTid) {
+ int interrogatingPid, long interrogatingTid) {
ViewRootImpl viewRootImpl = mViewRootImpl.get();
if (viewRootImpl != null && viewRootImpl.mView != null) {
viewRootImpl.getAccessibilityInteractionController()
.performAccessibilityActionClientThread(accessibilityNodeId, action, arguments,
- interactionId, callback, flags, interogatingPid, interrogatingTid);
+ interactionId, callback, flags, interrogatingPid, interrogatingTid);
} else {
// We cannot make the call and notify the caller so it does not wait.
try {
@@ -6669,6 +6696,26 @@
}
@Override
+ public void computeClickPointInScreen(long accessibilityNodeId, Region interactiveRegion,
+ int interactionId, IAccessibilityInteractionConnectionCallback callback,
+ int interrogatingPid, long interrogatingTid, MagnificationSpec spec) {
+ ViewRootImpl viewRootImpl = mViewRootImpl.get();
+ if (viewRootImpl != null && viewRootImpl.mView != null) {
+ viewRootImpl.getAccessibilityInteractionController()
+ .computeClickPointInScreenClientThread(accessibilityNodeId,
+ interactiveRegion, interactionId, callback, interrogatingPid,
+ interrogatingTid, spec);
+ } else {
+ // We cannot make the call and notify the caller so it does not wait.
+ try {
+ callback.setComputeClickPointInScreenActionResult(null, interactionId);
+ } catch (RemoteException re) {
+ /* best effort - ignore */
+ }
+ }
+ }
+
+ @Override
public void findAccessibilityNodeInfosByViewId(long accessibilityNodeId,
String viewId, Region interactiveRegion, int interactionId,
IAccessibilityInteractionConnectionCallback callback, int flags,
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 571a8f0..24c3c1a 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -378,35 +378,75 @@
}
/**
- * @hide
+ * Returns the top stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The top stable inset
*/
public int getStableInsetTop() {
return mStableInsets.top;
}
/**
- * @hide
+ * Returns the left stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The left stable inset
*/
public int getStableInsetLeft() {
return mStableInsets.left;
}
/**
- * @hide
+ * Returns the right stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The right stable inset
*/
public int getStableInsetRight() {
return mStableInsets.right;
}
/**
- * @hide
+ * Returns the bottom stable inset in pixels.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return The bottom stable inset
*/
public int getStableInsetBottom() {
return mStableInsets.bottom;
}
/**
- * @hide
+ * Returns true if this WindowInsets has nonzero stable insets.
+ *
+ * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+ * partially or fully obscured by the system UI elements. This value does not change
+ * based on the visibility state of those elements; for example, if the status bar is
+ * normally shown, but temporarily hidden, the stable inset will still provide the inset
+ * associated with the status bar being shown.</p>
+ *
+ * @return true if any of the stable inset values are nonzero
*/
public boolean hasStableInsets() {
return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0
@@ -414,7 +454,9 @@
}
/**
- * @hide
+ * Returns a copy of this WindowInsets with the stable insets fully consumed.
+ *
+ * @return A modified copy of this WindowInsets
*/
public WindowInsets consumeStableInsets() {
final WindowInsets result = new WindowInsets(this);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 053fdd0..2ed125d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -379,6 +379,10 @@
public static final int LID_CLOSED = 0;
public static final int LID_OPEN = 1;
+ public static final int CAMERA_LENS_COVER_ABSENT = -1;
+ public static final int CAMERA_LENS_UNCOVERED = 0;
+ public static final int CAMERA_LENS_COVERED = 1;
+
/**
* Ask the window manager to re-evaluate the system UI flags.
*/
@@ -399,6 +403,11 @@
public int getLidState();
/**
+ * Returns a code that descripbes whether the camera lens is covered or not.
+ */
+ public int getCameraLensCoverState();
+
+ /**
* Switch the keyboard layout for the given device.
* Direction should be +1 or -1 to go to the next or previous keyboard layout.
*/
@@ -761,7 +770,8 @@
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
/**
- * Called from the input reader thread before a motion is enqueued when the screen is off.
+ * Called from the input reader thread before a motion is enqueued when the device is in a
+ * non-interactive state.
*
* <p>There are some actions that need to be handled here because they
* affect the power state of the device, for example, waking on motions.
@@ -771,7 +781,7 @@
*
* @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
*/
- public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
+ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
/**
* Called from the input dispatcher thread before a key is dispatched to a window.
@@ -951,7 +961,14 @@
* @param lidOpen True if the lid is now open.
*/
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
-
+
+ /**
+ * Tell the policy that the camera lens has been covered or uncovered.
+ * @param whenNanos The time when the change occurred in uptime nanoseconds.
+ * @param lensCovered True if the lens is covered.
+ */
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
+
/**
* Tell the policy if anyone is requesting that keyguard not come on.
*
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index db78ec5..374f7e0 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.graphics.Point;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -98,6 +99,8 @@
private boolean mPerformAccessibilityActionResult;
+ private Point mComputeClickPointResult;
+
private Message mSameThreadMessage;
private static final SparseArray<IAccessibilityServiceConnection> sConnectionCache =
@@ -519,6 +522,43 @@
return false;
}
+ /**
+ * Computes a point in screen coordinates where sending a down/up events would
+ * perform a click on an {@link AccessibilityNodeInfo}.
+ *
+ * @param connectionId The id of a connection for interacting with the system.
+ * @param accessibilityWindowId A unique window id. Use
+ * {@link android.view.accessibility.AccessibilityNodeInfo#ACTIVE_WINDOW_ID}
+ * to query the currently active window.
+ * @param accessibilityNodeId A unique view id or virtual descendant id from
+ * where to start the search. Use
+ * {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
+ * to start from the root.
+ * @return Point the click point of null if no such point.
+ */
+ public Point computeClickPointInScreen(int connectionId, int accessibilityWindowId,
+ long accessibilityNodeId) {
+ try {
+ IAccessibilityServiceConnection connection = getConnection(connectionId);
+ if (connection != null) {
+ final int interactionId = mInteractionIdCounter.getAndIncrement();
+ final boolean success = connection.computeClickPointInScreen(
+ accessibilityWindowId, accessibilityNodeId,
+ interactionId, this, Thread.currentThread().getId());
+ if (success) {
+ return getComputeClickPointInScreenResultAndClear(interactionId);
+ }
+ } else {
+ if (DEBUG) {
+ Log.w(LOG_TAG, "No connection for connection id: " + connectionId);
+ }
+ }
+ } catch (RemoteException re) {
+ Log.w(LOG_TAG, "Error while calling remote computeClickPointInScreen", re);
+ }
+ return null;
+ }
+
public void clearCache() {
sAccessibilityCache.clear();
}
@@ -634,6 +674,34 @@
}
/**
+ * Gets the result of a request to compute a point in screen for clicking on a node.
+ *
+ * @param interactionId The interaction id to match the result with the request.
+ * @return The point or null if no such point.
+ */
+ private Point getComputeClickPointInScreenResultAndClear(int interactionId) {
+ synchronized (mInstanceLock) {
+ final boolean success = waitForResultTimedLocked(interactionId);
+ Point result = success ? mComputeClickPointResult : null;
+ clearResultLocked();
+ return result;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setComputeClickPointInScreenActionResult(Point point, int interactionId) {
+ synchronized (mInstanceLock) {
+ if (interactionId > mInteractionId) {
+ mComputeClickPointResult = point;
+ mInteractionId = interactionId;
+ }
+ mInstanceLock.notifyAll();
+ }
+ }
+
+ /**
* Clears the result state.
*/
private void clearResultLocked() {
@@ -641,6 +709,7 @@
mFindAccessibilityNodeInfoResult = null;
mFindAccessibilityNodeInfosResult = null;
mPerformAccessibilityActionResult = false;
+ mComputeClickPointResult = null;
}
/**
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
index faf7789..66a3f46 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl
@@ -17,6 +17,7 @@
package android.view.accessibility;
import android.graphics.Region;
+import android.graphics.Point;
import android.os.Bundle;
import android.view.MagnificationSpec;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -53,4 +54,8 @@
void performAccessibilityAction(long accessibilityNodeId, int action, in Bundle arguments,
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
int interrogatingPid, long interrogatingTid);
+
+ void computeClickPointInScreen(long accessibilityNodeId, in Region bounds, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
+ long interrogatingTid, in MagnificationSpec spec);
}
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index c1a3ab7..f480216 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -16,6 +16,7 @@
package android.view.accessibility;
+import android.graphics.Point;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.List;
@@ -51,4 +52,12 @@
* @param interactionId The interaction id to match the result with the request.
*/
void setPerformAccessibilityActionResult(boolean succeeded, int interactionId);
+
+ /**
+ * Sets the result of a request to compute a point for clicking in a view.
+ *
+ * @param point The point of null if no such point.
+ * @param interactionId The interaction id to match the result with the request.
+ */
+ void setComputeClickPointInScreenActionResult(in Point point, int interactionId);
}
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index fe0f5b9..600fffe 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -35,9 +35,21 @@
* actually inserted.</p>
*/
public final class CursorAnchorInfo implements Parcelable {
+ /**
+ * The index of the first character of the selected text (inclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionStart;
+ /**
+ * The index of the first character of the selected text (exclusive). {@code -1} when there is
+ * no text selection.
+ */
private final int mSelectionEnd;
+ /**
+ * The index of the first character of the composing text (inclusive). {@code -1} when there is
+ * no composing text.
+ */
private final int mComposingTextStart;
/**
* The text, tracked as a composing region.
@@ -82,7 +94,7 @@
* Java chars, in the local coordinates that will be transformed with the transformation matrix
* when rendered on the screen.
*/
- private final SparseRectFArray mCharacterRects;
+ private final SparseRectFArray mCharacterBoundsArray;
/**
* Transformation matrix that is applied to any positional information of this class to
@@ -91,18 +103,24 @@
private final Matrix mMatrix;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one visible region.
*/
public static final int FLAG_HAS_VISIBLE_REGION = 0x01;
/**
- * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterRectFlags(int)}: the
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
* insertion marker or character bounds have at least one invisible (clipped) region.
*/
public static final int FLAG_HAS_INVISIBLE_REGION = 0x02;
/**
+ * Flag for {@link #getInsertionMarkerFlags()} and {@link #getCharacterBoundsFlags(int)}: the
+ * insertion marker or character bounds is placed at right-to-left (RTL) character.
+ */
+ public static final int FLAG_IS_RTL = 0x04;
+
+ /**
* @removed
*/
public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
@@ -144,7 +162,7 @@
mInsertionMarkerTop = source.readFloat();
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
- mCharacterRects = source.readParcelable(SparseRectFArray.class.getClassLoader());
+ mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
mMatrix = new Matrix();
mMatrix.setValues(source.createFloatArray());
}
@@ -166,7 +184,7 @@
dest.writeFloat(mInsertionMarkerTop);
dest.writeFloat(mInsertionMarkerBaseline);
dest.writeFloat(mInsertionMarkerBottom);
- dest.writeParcelable(mCharacterRects, flags);
+ dest.writeParcelable(mCharacterBoundsArray, flags);
final float[] matrixArray = new float[9];
mMatrix.getValues(matrixArray);
dest.writeFloatArray(matrixArray);
@@ -174,7 +192,6 @@
@Override
public int hashCode(){
- // TODO: Improve the hash function.
final float floatHash = mInsertionMarkerHorizontal + mInsertionMarkerTop
+ mInsertionMarkerBaseline + mInsertionMarkerBottom;
int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
@@ -185,7 +202,7 @@
hash *= 31;
hash += Objects.hashCode(mComposingText);
hash *= 31;
- hash += Objects.hashCode(mCharacterRects);
+ hash += Objects.hashCode(mCharacterBoundsArray);
hash *= 31;
hash += Objects.hashCode(mMatrix);
return hash;
@@ -231,7 +248,7 @@
|| !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
return false;
}
- if (!Objects.equals(mCharacterRects, that.mCharacterRects)) {
+ if (!Objects.equals(mCharacterBoundsArray, that.mCharacterBoundsArray)) {
return false;
}
if (!Objects.equals(mMatrix, that.mMatrix)) {
@@ -250,7 +267,7 @@
+ " mInsertionMarkerTop=" + mInsertionMarkerTop
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
- + " mCharacterRects=" + Objects.toString(mCharacterRects)
+ + " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
+ " mMatrix=" + Objects.toString(mMatrix)
+ "}";
}
@@ -259,6 +276,19 @@
* Builder for {@link CursorAnchorInfo}. This class is not designed to be thread-safe.
*/
public static final class Builder {
+ private int mSelectionStart = -1;
+ private int mSelectionEnd = -1;
+ private int mComposingTextStart = -1;
+ private CharSequence mComposingText = null;
+ private float mInsertionMarkerHorizontal = Float.NaN;
+ private float mInsertionMarkerTop = Float.NaN;
+ private float mInsertionMarkerBaseline = Float.NaN;
+ private float mInsertionMarkerBottom = Float.NaN;
+ private int mInsertionMarkerFlags = 0;
+ private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
+ private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
+ private boolean mMatrixInitialized = false;
+
/**
* Sets the text range of the selection. Calling this can be skipped if there is no
* selection.
@@ -268,8 +298,6 @@
mSelectionEnd = newEnd;
return this;
}
- private int mSelectionStart = -1;
- private int mSelectionEnd = -1;
/**
* Sets the text range of the composing text. Calling this can be skipped if there is
@@ -288,8 +316,6 @@
}
return this;
}
- private int mComposingTextStart = -1;
- private CharSequence mComposingText = null;
/**
* @removed
@@ -335,11 +361,33 @@
mInsertionMarkerFlags = flags;
return this;
}
- private float mInsertionMarkerHorizontal = Float.NaN;
- private float mInsertionMarkerTop = Float.NaN;
- private float mInsertionMarkerBaseline = Float.NaN;
- private float mInsertionMarkerBottom = Float.NaN;
- private int mInsertionMarkerFlags = 0;
+
+ /**
+ * Adds the bounding box of the character specified with the index.
+ *
+ * @param index index of the character in Java chars units. Must be specified in
+ * ascending order across successive calls.
+ * @param left x coordinate of the left edge of the character in local coordinates.
+ * @param top y coordinate of the top edge of the character in local coordinates.
+ * @param right x coordinate of the right edge of the character in local coordinates.
+ * @param bottom y coordinate of the bottom edge of the character in local coordinates.
+ * @param flags flags for this character bounds. See {@link #FLAG_HAS_VISIBLE_REGION},
+ * {@link #FLAG_HAS_INVISIBLE_REGION} and {@link #FLAG_IS_RTL}. These flags must be
+ * specified when necessary.
+ * @throws IllegalArgumentException If the index is a negative value, or not greater than
+ * all of the previously called indices.
+ */
+ public Builder addCharacterBounds(final int index, final float left, final float top,
+ final float right, final float bottom, final int flags) {
+ if (index < 0) {
+ throw new IllegalArgumentException("index must not be a negative integer.");
+ }
+ if (mCharacterBoundsArrayBuilder == null) {
+ mCharacterBoundsArrayBuilder = new SparseRectFArrayBuilder();
+ }
+ mCharacterBoundsArrayBuilder.append(index, left, top, right, bottom, flags);
+ return this;
+ }
/**
* Adds the bounding box of the character specified with the index.
@@ -358,21 +406,25 @@
* example.
* @throws IllegalArgumentException If the index is a negative value, or not greater than
* all of the previously called indices.
+ * @removed
*/
public Builder addCharacterRect(final int index, final float leadingEdgeX,
final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY,
final int flags) {
- if (index < 0) {
- throw new IllegalArgumentException("index must not be a negative integer.");
+ final int newFlags;
+ final float left;
+ final float right;
+ if (leadingEdgeX <= trailingEdgeX) {
+ newFlags = flags;
+ left = leadingEdgeX;
+ right = trailingEdgeX;
+ } else {
+ newFlags = flags | FLAG_IS_RTL;
+ left = trailingEdgeX;
+ right = leadingEdgeX;
}
- if (mCharacterRectBuilder == null) {
- mCharacterRectBuilder = new SparseRectFArrayBuilder();
- }
- mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
- trailingEdgeY, flags);
- return this;
+ return addCharacterBounds(index, left, leadingEdgeY, right, trailingEdgeY, newFlags);
}
- private SparseRectFArrayBuilder mCharacterRectBuilder = null;
/**
* Sets the matrix that transforms local coordinates into screen coordinates.
@@ -384,8 +436,6 @@
mMatrixInitialized = true;
return this;
}
- private final Matrix mMatrix = new Matrix(Matrix.IDENTITY_MATRIX);
- private boolean mMatrixInitialized = false;
/**
* @return {@link CursorAnchorInfo} using parameters in this {@link Builder}.
@@ -394,13 +444,15 @@
*/
public CursorAnchorInfo build() {
if (!mMatrixInitialized) {
- // Coordinate transformation matrix is mandatory when positional parameters are
- // specified.
- if ((mCharacterRectBuilder != null && !mCharacterRectBuilder.isEmpty()) ||
- !Float.isNaN(mInsertionMarkerHorizontal) ||
- !Float.isNaN(mInsertionMarkerTop) ||
- !Float.isNaN(mInsertionMarkerBaseline) ||
- !Float.isNaN(mInsertionMarkerBottom)) {
+ // Coordinate transformation matrix is mandatory when at least one positional
+ // parameter is specified.
+ final boolean hasCharacterBounds = (mCharacterBoundsArrayBuilder != null
+ && !mCharacterBoundsArrayBuilder.isEmpty());
+ if (hasCharacterBounds
+ || !Float.isNaN(mInsertionMarkerHorizontal)
+ || !Float.isNaN(mInsertionMarkerTop)
+ || !Float.isNaN(mInsertionMarkerBaseline)
+ || !Float.isNaN(mInsertionMarkerBottom)) {
throw new IllegalArgumentException("Coordinate transformation matrix is " +
"required when positional parameters are specified.");
}
@@ -424,8 +476,8 @@
mInsertionMarkerBottom = Float.NaN;
mMatrix.set(Matrix.IDENTITY_MATRIX);
mMatrixInitialized = false;
- if (mCharacterRectBuilder != null) {
- mCharacterRectBuilder.reset();
+ if (mCharacterBoundsArrayBuilder != null) {
+ mCharacterBoundsArrayBuilder.reset();
}
}
}
@@ -440,8 +492,8 @@
mInsertionMarkerTop = builder.mInsertionMarkerTop;
mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
- mCharacterRects = builder.mCharacterRectBuilder != null ?
- builder.mCharacterRectBuilder.build() : null;
+ mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null ?
+ builder.mCharacterBoundsArrayBuilder.build() : null;
mMatrix = new Matrix(builder.mMatrix);
}
@@ -539,6 +591,19 @@
/**
* Returns a new instance of {@link RectF} that indicates the location of the character
* specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return the character bounds in local coordinates as a new instance of {@link RectF}.
+ */
+ public RectF getCharacterBounds(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return null;
+ }
+ return mCharacterBoundsArray.get(index);
+ }
+
+ /**
+ * Returns a new instance of {@link RectF} that indicates the location of the character
+ * specified with the index.
* <p>
* Note that coordinates are not necessarily contiguous or even monotonous, especially when
* RTL text and LTR text are mixed.
@@ -549,28 +614,32 @@
* the location. Note that the {@code left} field can be greater than the {@code right} field
* if the character is in RTL text. Returns {@code null} if no location information is
* available.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public RectF getCharacterRect(final int index) {
- if (mCharacterRects == null) {
- return null;
+ return getCharacterBounds(index);
+ }
+
+ /**
+ * Returns the flags associated with the character bounds specified with the index.
+ * @param index index of the character in a Java chars.
+ * @return {@code 0} if no flag is specified.
+ */
+ public int getCharacterBoundsFlags(final int index) {
+ if (mCharacterBoundsArray == null) {
+ return 0;
}
- return mCharacterRects.get(index);
+ return mCharacterBoundsArray.getFlags(index, 0);
}
/**
* Returns the flags associated with the character rect specified with the index.
* @param index index of the character in a Java chars.
* @return {@code 0} if no flag is specified.
+ * @removed
*/
- // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
- // characters, and non-graphical chars.
public int getCharacterRectFlags(final int index) {
- if (mCharacterRects == null) {
- return 0;
- }
- return mCharacterRects.getFlags(index, 0);
+ return getCharacterBoundsFlags(index);
}
/**
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
index dc7c808..b46ac9a 100644
--- a/core/java/android/webkit/WebResourceRequest.java
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -41,7 +41,7 @@
boolean isForMainFrame();
/**
- * Gets whether a gesture was associated with the request.
+ * Gets whether a gesture (such as a link click) was associated with the request.
* <p>
* <strong>IMPORTANT:</strong>
* This should not be used to implement any form of security. It is possible for the content
@@ -49,6 +49,11 @@
*
* @return whether a gesture was associated with the request.
*/
+ boolean hasGesture();
+
+ /*
+ * @removed
+ */
boolean hasUserGestureInsecure();
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index edfa7af3..081bfdf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1939,16 +1939,14 @@
*
* @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the Webview's
* zoom limits. This value must be in the range 0.01 to 100.0 inclusive.
- *
- * @return false if no zoom changes, true otherwise.
*/
- public boolean zoomBy(float zoomFactor) {
+ public void zoomBy(float zoomFactor) {
checkThread();
if (zoomFactor < 0.01)
throw new IllegalArgumentException("zoomFactor must be greater than 0.01.");
if (zoomFactor > 100.0)
throw new IllegalArgumentException("zoomFactor must be less than 100.");
- return mProvider.zoomBy(zoomFactor);
+ mProvider.zoomBy(zoomFactor);
}
/**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index eef8554..94d52d5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3325,8 +3325,8 @@
}
if (dispatchNestedPreScroll(0, -rawDeltaY, mScrollConsumed, mScrollOffset)) {
rawDeltaY += mScrollConsumed[1];
- scrollOffsetCorrection -= mScrollOffset[1];
- scrollConsumedCorrection -= mScrollConsumed[1];
+ scrollOffsetCorrection = -mScrollOffset[1];
+ scrollConsumedCorrection = mScrollConsumed[1];
if (vtev != null) {
vtev.offsetLocation(0, mScrollOffset[1]);
}
@@ -3437,7 +3437,7 @@
}
}
}
- mMotionY = y + scrollOffsetCorrection;
+ mMotionY = y + lastYCorrection + scrollOffsetCorrection;
}
mLastY = y + lastYCorrection + scrollOffsetCorrection;
}
@@ -3505,10 +3505,10 @@
mMotionCorrection = 0;
View motionView = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = motionView != null ? motionView.getTop() : 0;
- mMotionY = y;
+ mMotionY = y + scrollOffsetCorrection;
mMotionPosition = motionPosition;
}
- mLastY = y;
+ mLastY = y + lastYCorrection + scrollOffsetCorrection;
mDirection = newDirection;
}
}
@@ -3876,7 +3876,7 @@
if (mPositionScroller != null) {
mPositionScroller.stop();
}
- if (flingVelocity) {
+ if (flingVelocity && !dispatchNestedPreFling(0, -initialVelocity)) {
dispatchNestedFling(0, -initialVelocity, false);
}
}
@@ -4001,14 +4001,15 @@
* <p>Applications can use this method to manually initiate a fling as if the user
* initiated it via touch interaction.</p>
*
- * @param velocityY Vertical velocity in pixels per second
+ * @param velocityY Vertical velocity in pixels per second. Note that this is velocity of
+ * content, not velocity of a touch that initiated the fling.
*/
public void fling(int velocityY) {
if (mFlingRunnable == null) {
mFlingRunnable = new FlingRunnable();
}
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
- mFlingRunnable.start(-velocityY);
+ mFlingRunnable.start(velocityY);
}
@Override
diff --git a/core/java/android/widget/ActionMenuView.java b/core/java/android/widget/ActionMenuView.java
index 96abf51..7198e52 100644
--- a/core/java/android/widget/ActionMenuView.java
+++ b/core/java/android/widget/ActionMenuView.java
@@ -29,6 +29,7 @@
import com.android.internal.view.menu.ActionMenuItemView;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.view.menu.MenuView;
/**
@@ -53,6 +54,8 @@
private boolean mReserveOverflow;
private ActionMenuPresenter mPresenter;
+ private MenuPresenter.Callback mActionMenuPresenterCallback;
+ private MenuBuilder.Callback mMenuBuilderCallback;
private boolean mFormatItems;
private int mFormatItemsWidth;
private int mMinCellSize;
@@ -608,7 +611,9 @@
mMenu = new MenuBuilder(context);
mMenu.setCallback(new MenuBuilderCallback());
mPresenter = new ActionMenuPresenter(context);
- mPresenter.setCallback(new ActionMenuPresenterCallback());
+ mPresenter.setReserveOverflow(true);
+ mPresenter.setCallback(mActionMenuPresenterCallback != null
+ ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
mMenu.addMenuPresenter(mPresenter, mPopupContext);
mPresenter.setMenuView(this);
}
@@ -617,6 +622,15 @@
}
/**
+ * Must be called before the first call to getMenu()
+ * @hide
+ */
+ public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+ mActionMenuPresenterCallback = pcb;
+ mMenuBuilderCallback = mcb;
+ }
+
+ /**
* Returns the current menu or null if one has not yet been configured.
* @hide Internal use only for action bar integration
*/
@@ -719,6 +733,9 @@
@Override
public void onMenuModeChange(MenuBuilder menu) {
+ if (mMenuBuilderCallback != null) {
+ mMenuBuilderCallback.onMenuModeChange(menu);
+ }
}
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 26c1f96..d77f0b2 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -71,9 +71,9 @@
* @attr ref android.R.styleable#DatePicker_minDate
* @attr ref android.R.styleable#DatePicker_spinnersShown
* @attr ref android.R.styleable#DatePicker_calendarViewShown
- * @attr ref android.R.styleable#DatePicker_dayOfWeekBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_dayOfWeekBackground
* @attr ref android.R.styleable#DatePicker_dayOfWeekTextAppearance
- * @attr ref android.R.styleable#DatePicker_headerBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_headerBackground
* @attr ref android.R.styleable#DatePicker_headerMonthTextAppearance
* @attr ref android.R.styleable#DatePicker_headerDayOfMonthTextAppearance
* @attr ref android.R.styleable#DatePicker_headerYearTextAppearance
@@ -125,6 +125,7 @@
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
defStyleAttr, defStyleRes);
final int mode = a.getInt(R.styleable.DatePicker_datePickerMode, MODE_SPINNER);
+ final int firstDayOfWeek = a.getInt(R.styleable.DatePicker_firstDayOfWeek, 0);
a.recycle();
switch (mode) {
@@ -136,6 +137,10 @@
mDelegate = createSpinnerUIDelegate(context, attrs, defStyleAttr, defStyleRes);
break;
}
+
+ if (firstDayOfWeek != 0) {
+ setFirstDayOfWeek(firstDayOfWeek);
+ }
}
private DatePickerDelegate createSpinnerUIDelegate(Context context, AttributeSet attrs,
@@ -300,6 +305,47 @@
}
/**
+ * Sets the first day of week.
+ *
+ * @param firstDayOfWeek The first day of the week conforming to the
+ * {@link CalendarView} APIs.
+ * @see Calendar#SUNDAY
+ * @see Calendar#MONDAY
+ * @see Calendar#TUESDAY
+ * @see Calendar#WEDNESDAY
+ * @see Calendar#THURSDAY
+ * @see Calendar#FRIDAY
+ * @see Calendar#SATURDAY
+ *
+ * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+ */
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ if (firstDayOfWeek < Calendar.SUNDAY || firstDayOfWeek > Calendar.SATURDAY) {
+ throw new IllegalArgumentException("firstDayOfWeek must be between 1 and 7");
+ }
+ mDelegate.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ /**
+ * Gets the first day of week.
+ *
+ * @return The first day of the week conforming to the {@link CalendarView}
+ * APIs.
+ * @see Calendar#SUNDAY
+ * @see Calendar#MONDAY
+ * @see Calendar#TUESDAY
+ * @see Calendar#WEDNESDAY
+ * @see Calendar#THURSDAY
+ * @see Calendar#FRIDAY
+ * @see Calendar#SATURDAY
+ *
+ * @attr ref android.R.styleable#DatePicker_firstDayOfWeek
+ */
+ public int getFirstDayOfWeek() {
+ return mDelegate.getFirstDayOfWeek();
+ }
+
+ /**
* Gets whether the {@link CalendarView} is shown.
*
* @return True if the calendar view is shown.
@@ -315,7 +361,7 @@
* @return The calendar view.
* @see #getCalendarViewShown()
*/
- public CalendarView getCalendarView () {
+ public CalendarView getCalendarView() {
return mDelegate.getCalendarView();
}
@@ -382,6 +428,9 @@
int getMonth();
int getDayOfMonth();
+ void setFirstDayOfWeek(int firstDayOfWeek);
+ int getFirstDayOfWeek();
+
void setMinDate(long minDate);
Calendar getMinDate();
@@ -699,6 +748,16 @@
}
@Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ @Override
+ public int getFirstDayOfWeek() {
+ return mCalendarView.getFirstDayOfWeek();
+ }
+
+ @Override
public void setMinDate(long minDate) {
mTempDate.setTimeInMillis(minDate);
if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 7df1fa3..b962962 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -21,7 +21,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
@@ -49,6 +49,7 @@
*/
class DatePickerCalendarDelegate extends DatePicker.AbstractDatePickerDelegate implements
View.OnClickListener, DatePickerController {
+ private static final int USE_LOCALE = 0;
private static final int UNINITIALIZED = -1;
private static final int MONTH_AND_DAY_VIEW = 0;
@@ -99,6 +100,8 @@
private Calendar mMinDate;
private Calendar mMaxDate;
+ private int mFirstDayOfWeek = USE_LOCALE;
+
private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
public DatePickerCalendarDelegate(DatePicker delegator, Context context, AttributeSet attrs,
@@ -149,16 +152,12 @@
mDayOfWeekView.setTextAppearance(context, dayOfWeekTextAppearanceResId);
}
- final int dayOfWeekBackgroundColor = a.getColor(
- R.styleable.DatePicker_dayOfWeekBackgroundColor, Color.TRANSPARENT);
- mDayOfWeekView.setBackgroundColor(dayOfWeekBackgroundColor);
+ mDayOfWeekView.setBackground(a.getDrawable(R.styleable.DatePicker_dayOfWeekBackground));
+
+ dateLayout.setBackground(a.getDrawable(R.styleable.DatePicker_headerBackground));
final int headerSelectedTextColor = a.getColor(
R.styleable.DatePicker_headerSelectedTextColor, defaultHighlightColor);
- final int headerBackgroundColor = a.getColor(R.styleable.DatePicker_headerBackgroundColor,
- Color.TRANSPARENT);
- dateLayout.setBackgroundColor(headerBackgroundColor);
-
final int monthTextAppearanceResId = a.getResourceId(
R.styleable.DatePicker_headerMonthTextAppearance, -1);
if (monthTextAppearanceResId != -1) {
@@ -442,7 +441,15 @@
}
@Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mFirstDayOfWeek = firstDayOfWeek;
+ }
+
+ @Override
public int getFirstDayOfWeek() {
+ if (mFirstDayOfWeek != USE_LOCALE) {
+ return mFirstDayOfWeek;
+ }
return mCurrentDate.getFirstDayOfWeek();
}
diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java
index 6a074da..059709d 100644
--- a/core/java/android/widget/DatePickerController.java
+++ b/core/java/android/widget/DatePickerController.java
@@ -35,6 +35,7 @@
Calendar getSelectedDay();
+ void setFirstDayOfWeek(int firstDayOfWeek);
int getFirstDayOfWeek();
int getMinYear();
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 57b8dcb..033b99a 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -52,12 +52,15 @@
private static final String TAG = "EdgeEffect";
// Time it will take the effect to fully recede in ms
- private static final int RECEDE_TIME = 1000;
+ private static final int RECEDE_TIME = 600;
// Time it will take before a pulled glow begins receding in ms
private static final int PULL_TIME = 167;
- private static final float MAX_ALPHA = 1.f;
+ // Time it will take in ms for a pulled glow to decay to partial strength before release
+ private static final int PULL_DECAY_TIME = 2000;
+
+ private static final float MAX_ALPHA = 0.5f;
private static final float MAX_GLOW_SCALE = 2.f;
@@ -93,12 +96,9 @@
private static final int STATE_RECEDE = 3;
private static final int STATE_PULL_DECAY = 4;
- // How much dragging should effect the height of the glow image.
- // Number determined by user testing.
- private static final int PULL_DISTANCE_GLOW_FACTOR = 7;
- private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f;
+ private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 0.8f;
- private static final int VELOCITY_GLOW_FACTOR = 12;
+ private static final int VELOCITY_GLOW_FACTOR = 6;
private int mState = STATE_IDLE;
@@ -107,7 +107,7 @@
private final Rect mBounds = new Rect();
private final Paint mPaint = new Paint();
private float mRadius;
- private float mBaseGlowHeight;
+ private float mBaseGlowScale;
private float mDisplacement = 0.5f;
private float mTargetDisplacement = 0.5f;
@@ -138,8 +138,12 @@
final float r = width * 0.75f / SIN;
final float y = COS * r;
final float h = r - y;
+ final float or = height * 0.75f / SIN;
+ final float oy = COS * or;
+ final float oh = or - oy;
+
mRadius = r;
- mBaseGlowHeight = h;
+ mBaseGlowScale = h > 0 ? Math.min(oh / h, 1.f) : 1.f;
mBounds.set(mBounds.left, mBounds.top, width, (int) Math.min(height, h));
}
@@ -319,13 +323,14 @@
final float centerX = mBounds.centerX();
final float centerY = mBounds.height() - mRadius;
- canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0);
+ canvas.scale(1.f, Math.min(mGlowScaleY, 1.f) * mBaseGlowScale, centerX, 0);
final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
float translateX = mBounds.width() * displacement / 2;
canvas.clipRect(mBounds);
canvas.translate(translateX, 0);
+ mPaint.setAlpha((int) (0xff * mGlowAlpha));
canvas.drawCircle(centerX, centerY, mRadius, mPaint);
canvas.restoreToCount(count);
@@ -372,7 +377,16 @@
mGlowScaleYFinish = 0.f;
break;
case STATE_PULL:
- // Hold in this state until explicitly released.
+ mState = STATE_PULL_DECAY;
+ mStartTime = AnimationUtils.currentAnimationTimeMillis();
+ mDuration = PULL_DECAY_TIME;
+
+ mGlowAlphaStart = mGlowAlpha;
+ mGlowScaleYStart = mGlowScaleY;
+
+ // After pull, the glow should fade to nothing.
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
break;
case STATE_PULL_DECAY:
mState = STATE_RECEDE;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 22138d0..3f168e8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3060,47 +3060,69 @@
final CharSequence composingText = text.subSequence(composingTextStart,
composingTextEnd);
builder.setComposingText(composingTextStart, composingText);
- }
- // TODO: Optimize this loop by caching the result.
- for (int offset = composingTextStart; offset < composingTextEnd; offset++) {
- if (offset < 0) {
- continue;
+
+ final int minLine = layout.getLineForOffset(composingTextStart);
+ final int maxLine = layout.getLineForOffset(composingTextEnd - 1);
+ for (int line = minLine; line <= maxLine; ++line) {
+ final int lineStart = layout.getLineStart(line);
+ final int lineEnd = layout.getLineEnd(line);
+ final int offsetStart = Math.max(lineStart, composingTextStart);
+ final int offsetEnd = Math.min(lineEnd, composingTextEnd);
+ final boolean ltrLine =
+ layout.getParagraphDirection(line) == Layout.DIR_LEFT_TO_RIGHT;
+ final float[] widths = new float[offsetEnd - offsetStart];
+ layout.getPaint().getTextWidths(text, offsetStart, offsetEnd, widths);
+ final float top = layout.getLineTop(line);
+ final float bottom = layout.getLineBottom(line);
+ for (int offset = offsetStart; offset < offsetEnd; ++offset) {
+ final float charWidth = widths[offset - offsetStart];
+ final boolean isRtl = layout.isRtlCharAt(offset);
+ final float primary = layout.getPrimaryHorizontal(offset);
+ final float secondary = layout.getSecondaryHorizontal(offset);
+ // TODO: This doesn't work perfectly for text with custom styles and
+ // TAB chars.
+ final float left;
+ final float right;
+ if (ltrLine) {
+ if (isRtl) {
+ left = secondary - charWidth;
+ right = secondary;
+ } else {
+ left = primary;
+ right = primary + charWidth;
+ }
+ } else {
+ if (!isRtl) {
+ left = secondary;
+ right = secondary + charWidth;
+ } else {
+ left = primary - charWidth;
+ right = primary;
+ }
+ }
+ // TODO: Check top-right and bottom-left as well.
+ final float localLeft = left + viewportToContentHorizontalOffset;
+ final float localRight = right + viewportToContentHorizontalOffset;
+ final float localTop = top + viewportToContentVerticalOffset;
+ final float localBottom = bottom + viewportToContentVerticalOffset;
+ final boolean isTopLeftVisible = isPositionVisible(localLeft, localTop);
+ final boolean isBottomRightVisible =
+ isPositionVisible(localRight, localBottom);
+ int characterBoundsFlags = 0;
+ if (isTopLeftVisible || isBottomRightVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+ }
+ if (!isTopLeftVisible || !isTopLeftVisible) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+ }
+ if (isRtl) {
+ characterBoundsFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
+ // Here offset is the index in Java chars.
+ builder.addCharacterBounds(offset, localLeft, localTop, localRight,
+ localBottom, characterBoundsFlags);
+ }
}
- final boolean isRtl = layout.isRtlCharAt(offset);
- final int line = layout.getLineForOffset(offset);
- final int nextCharIndex = offset + 1;
- final float localLeadingEdgeX = layout.getPrimaryHorizontal(offset);
- final float localTrailingEdgeX;
- if (nextCharIndex != layout.getLineEnd(line)) {
- localTrailingEdgeX = layout.getPrimaryHorizontal(nextCharIndex);
- } else if (isRtl) {
- localTrailingEdgeX = layout.getLineLeft(line);
- } else {
- localTrailingEdgeX = layout.getLineRight(line);
- }
- final float leadingEdgeX = localLeadingEdgeX
- + viewportToContentHorizontalOffset;
- final float trailingEdgeX = localTrailingEdgeX
- + viewportToContentHorizontalOffset;
- final float top = layout.getLineTop(line) + viewportToContentVerticalOffset;
- final float bottom = layout.getLineBottom(line)
- + viewportToContentVerticalOffset;
- // TODO: Check right-top and left-bottom as well.
- final boolean isLeadingEdgeTopVisible = isPositionVisible(leadingEdgeX, top);
- final boolean isTrailingEdgeBottomVisible =
- isPositionVisible(trailingEdgeX, bottom);
- int characterRectFlags = 0;
- if (isLeadingEdgeTopVisible || isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
- }
- if (!isLeadingEdgeTopVisible || !isTrailingEdgeBottomVisible) {
- characterRectFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
- }
- // Here offset is the index in Java chars.
- // TODO: We must have a well-defined specification. For example, how
- // surrogate pairs and composition letters are handled must be documented.
- builder.addCharacterRect(offset, leadingEdgeX, top, trailingEdgeX, bottom,
- characterRectFlags);
}
}
@@ -3127,6 +3149,9 @@
if (!isTopVisible || !isBottomVisible) {
insertionMarkerFlags |= CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
}
+ if (layout.isRtlCharAt(offset)) {
+ insertionMarkerFlags |= CursorAnchorInfo.FLAG_IS_RTL;
+ }
builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
insertionMarkerBaseline, insertionMarkerBottom, insertionMarkerFlags);
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index d263625..efd6fc0 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -2356,7 +2356,7 @@
final int rowsCount = getCount() / columnsCount;
final int selectionMode = getSelectionModeForAccessibility();
final CollectionInfo collectionInfo = CollectionInfo.obtain(
- columnsCount, rowsCount, false, selectionMode);
+ rowsCount, columnsCount, false, selectionMode);
info.setCollectionInfo(collectionInfo);
}
@@ -2385,7 +2385,7 @@
final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
final boolean isSelected = isItemChecked(position);
final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
- column, 1, row, 1, isHeading, isSelected);
+ row, 1, column, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1368cd3..2e9858c 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3882,9 +3882,10 @@
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ListView.class.getName());
- final int count = getCount();
+ final int rowsCount = getCount();
final int selectionMode = getSelectionModeForAccessibility();
- final CollectionInfo collectionInfo = CollectionInfo.obtain(1, count, false, selectionMode);
+ final CollectionInfo collectionInfo = CollectionInfo.obtain(
+ rowsCount, 1, false, selectionMode);
info.setCollectionInfo(collectionInfo);
}
@@ -3897,7 +3898,7 @@
final boolean isHeading = lp != null && lp.viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
final boolean isSelected = isItemChecked(position);
final CollectionItemInfo itemInfo = CollectionItemInfo.obtain(
- 0, 1, position, 1, isHeading, isSelected);
+ position, 1, 0, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 345eafb..ee17b78 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1878,9 +1878,6 @@
if (mOnValueChangeListener != null) {
mOnValueChangeListener.onValueChange(this, previous, mValue);
}
-
- mAccessibilityNodeProvider.sendAccessibilityEventForVirtualText(
- AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
/**
@@ -2559,7 +2556,6 @@
getLocationOnScreen(locationOnScreen);
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
info.setBoundsInScreen(boundsInScreen);
- info.setLiveRegion(View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE);
return info;
}
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index adca4cc..d2f68d0 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -458,6 +458,7 @@
a.recycle();
setOnTouchListener(this);
+ setClickable(true);
// Initial values
final Calendar calendar = Calendar.getInstance(Locale.getDefault());
@@ -612,9 +613,9 @@
mMinutesTexts[i] = String.format("%02d", MINUTES_NUMBERS[i]);
}
- String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
- mAmPmText[AM] = amPmTexts[0];
- mAmPmText[PM] = amPmTexts[1];
+ String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(mContext);
+ mAmPmText[AM] = amPmStrings[0];
+ mAmPmText[PM] = amPmStrings[1];
}
private void initData() {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 69d5f40..90e9c69 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -22,11 +22,13 @@
import android.app.PendingIntent;
import android.appwidget.AppWidgetHostView;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.Rect;
@@ -1653,8 +1655,10 @@
*
* @param application The application whose content is shown by the views.
* @param layoutId The id of the layout resource.
+ *
+ * @hide
*/
- private RemoteViews(ApplicationInfo application, int layoutId) {
+ protected RemoteViews(ApplicationInfo application, int layoutId) {
mApplication = application;
mLayoutId = layoutId;
mBitmapCache = new BitmapCache();
@@ -2515,15 +2519,29 @@
RemoteViews rvToApply = getRemoteViewsToApply(context);
View result;
-
- Context c = prepareContext(context);
+ // RemoteViews may be built by an application installed in another
+ // user. So build a context that loads resources from that user but
+ // still returns the current users userId so settings like data / time formats
+ // are loaded without requiring cross user persmissions.
+ final Context contextForResources = getContextForResources(context);
+ Context inflationContext = new ContextWrapper(context) {
+ @Override
+ public Resources getResources() {
+ return contextForResources.getResources();
+ }
+ @Override
+ public Resources.Theme getTheme() {
+ return contextForResources.getTheme();
+ }
+ };
LayoutInflater inflater = (LayoutInflater)
- c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater = inflater.cloneInContext(c);
+ // Clone inflater so we load resources from correct context and
+ // we don't add a filter to the static version returned by getSystemService.
+ inflater = inflater.cloneInContext(inflationContext);
inflater.setFilter(this);
-
result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
rvToApply.performApply(result, parent, handler);
@@ -2557,7 +2575,6 @@
}
}
- prepareContext(context);
rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
}
@@ -2572,7 +2589,7 @@
}
}
- private Context prepareContext(Context context) {
+ private Context getContextForResources(Context context) {
if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
&& context.getPackageName().equals(mApplication.packageName)) {
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 0a3c7ff..0289ccc 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -334,6 +334,10 @@
setInputType(inputType);
}
+ boolean focusable = true;
+ focusable = a.getBoolean(R.styleable.SearchView_focusable, focusable);
+ setFocusable(focusable);
+
a.recycle();
// Save voice intent for later queries/launching
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3e1b674..80ea6ea 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8423,6 +8423,33 @@
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK: {
+ boolean handled = false;
+
+ // Simulate View.onTouchEvent for an ACTION_UP event.
+ if (isClickable() || isLongClickable()) {
+ if (isFocusable() && !isFocused()) {
+ requestFocus();
+ }
+
+ performClick();
+ handled = true;
+ }
+
+ // Simulate TextView.onTouchEvent for an ACTION_UP event.
+ if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
+ && mText instanceof Spannable && mLayout != null
+ && (isTextEditable() || isTextSelectable()) && isFocused()) {
+ // Show the IME, except when selecting in read-only text.
+ final InputMethodManager imm = InputMethodManager.peekInstance();
+ viewClicked(imm);
+ if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {
+ handled |= imm.showSoftInput(this, 0);
+ }
+ }
+
+ return handled;
+ }
case AccessibilityNodeInfo.ACTION_COPY: {
if (isFocused() && canCopy()) {
if (onTextContextMenuItem(ID_COPY)) {
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 6169d2e..73e05e8 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -21,7 +21,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -40,7 +39,6 @@
import com.android.internal.R;
-import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
@@ -71,6 +69,7 @@
private static final int HOURS_IN_HALF_DAY = 12;
+ private View mHeaderView;
private TextView mHourView;
private TextView mMinuteView;
private TextView mAmPmTextView;
@@ -156,11 +155,8 @@
mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance);
}
- final int headerBackgroundColor = a.getColor(
- R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT);
- if (headerBackgroundColor != Color.TRANSPARENT) {
- mainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor);
- }
+ mHeaderView = mainView.findViewById(R.id.time_header);
+ mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
a.recycle();
@@ -194,14 +190,11 @@
}
private void setupListeners() {
- KeyboardListener keyboardListener = new KeyboardListener();
- mDelegator.setOnKeyListener(keyboardListener);
+ mHeaderView.setOnKeyListener(mKeyListener);
+ mHeaderView.setOnFocusChangeListener(mFocusListener);
+ mHeaderView.setFocusable(true);
- mHourView.setOnKeyListener(keyboardListener);
- mMinuteView.setOnKeyListener(keyboardListener);
- mAmPmTextView.setOnKeyListener(keyboardListener);
mRadialTimePickerView.setOnValueSelectedListener(this);
- mRadialTimePickerView.setOnKeyListener(keyboardListener);
mHourView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -641,7 +634,7 @@
if (!isTypedTimeFullyLegal()) {
mTypedTimes.clear();
}
- finishKbMode(true);
+ finishKbMode();
}
}
@@ -776,27 +769,7 @@
* @return true if the key was successfully processed, false otherwise.
*/
private boolean processKeyUp(int keyCode) {
- if (keyCode == KeyEvent.KEYCODE_ESCAPE || keyCode == KeyEvent.KEYCODE_TAB) {
- if(mInKbMode) {
- if (isTypedTimeFullyLegal()) {
- finishKbMode(true);
- }
- return true;
- }
- } else if (keyCode == KeyEvent.KEYCODE_ENTER) {
- if (mInKbMode) {
- if (!isTypedTimeFullyLegal()) {
- return true;
- }
- finishKbMode(false);
- }
- if (mOnTimeChangedListener != null) {
- mOnTimeChangedListener.onTimeChanged(mDelegator,
- mRadialTimePickerView.getCurrentHour(),
- mRadialTimePickerView.getCurrentMinute());
- }
- return true;
- } else if (keyCode == KeyEvent.KEYCODE_DEL) {
+ if (keyCode == KeyEvent.KEYCODE_DEL) {
if (mInKbMode) {
if (!mTypedTimes.isEmpty()) {
int deleted = deleteLastTypedKey();
@@ -925,9 +898,8 @@
/**
* Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
- * @param updateDisplays If true, update the displays with the relevant time.
*/
- private void finishKbMode(boolean updateDisplays) {
+ private void finishKbMode() {
mInKbMode = false;
if (!mTypedTimes.isEmpty()) {
int values[] = getEnteredTime(null);
@@ -938,10 +910,8 @@
}
mTypedTimes.clear();
}
- if (updateDisplays) {
- updateDisplay(false);
- mRadialTimePickerView.setInputEnabled(true);
- }
+ updateDisplay(false);
+ mRadialTimePickerView.setInputEnabled(true);
}
/**
@@ -1261,7 +1231,7 @@
}
}
- private class KeyboardListener implements View.OnKeyListener {
+ private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP) {
@@ -1269,5 +1239,20 @@
}
return false;
}
- }
+ };
+
+ private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) {
+ finishKbMode();
+
+ if (mOnTimeChangedListener != null) {
+ mOnTimeChangedListener.onTimeChanged(mDelegator,
+ mRadialTimePickerView.getCurrentHour(),
+ mRadialTimePickerView.getCurrentMinute());
+ }
+ }
+ }
+ };
}
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 3ba03b8..be28199 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -37,6 +37,7 @@
import android.view.ViewGroup;
import com.android.internal.R;
+import com.android.internal.app.ToolbarActionBar;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
import com.android.internal.view.menu.MenuPresenter;
@@ -153,6 +154,8 @@
private ToolbarWidgetWrapper mWrapper;
private ActionMenuPresenter mOuterActionMenuPresenter;
private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
+ private MenuPresenter.Callback mActionMenuPresenterCallback;
+ private MenuBuilder.Callback mMenuBuilderCallback;
private boolean mCollapsible;
@@ -825,6 +828,7 @@
mMenuView = new ActionMenuView(getContext());
mMenuView.setPopupTheme(mPopupTheme);
mMenuView.setOnMenuItemClickListener(mMenuViewItemClickListener);
+ mMenuView.setMenuCallbacks(mActionMenuPresenterCallback, mMenuBuilderCallback);
final LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = Gravity.END | (mButtonGravity & Gravity.VERTICAL_GRAVITY_MASK);
mMenuView.setLayoutParams(lp);
@@ -1678,6 +1682,15 @@
}
/**
+ * Must be called before the menu is accessed
+ * @hide
+ */
+ public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
+ mActionMenuPresenterCallback = pcb;
+ mMenuBuilderCallback = mcb;
+ }
+
+ /**
* Interface responsible for receiving menu item click events if the items themselves
* do not have individual item click listeners.
*/
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index c409520..6d5c98e 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -63,63 +63,46 @@
private final Context mContext;
private final DialogInterface mDialogInterface;
private final Window mWindow;
-
+
private CharSequence mTitle;
-
private CharSequence mMessage;
-
private ListView mListView;
-
private View mView;
private int mViewLayoutResId;
private int mViewSpacingLeft;
-
private int mViewSpacingTop;
-
private int mViewSpacingRight;
-
private int mViewSpacingBottom;
-
private boolean mViewSpacingSpecified = false;
-
+
private Button mButtonPositive;
-
private CharSequence mButtonPositiveText;
-
private Message mButtonPositiveMessage;
private Button mButtonNegative;
-
private CharSequence mButtonNegativeText;
-
private Message mButtonNegativeMessage;
private Button mButtonNeutral;
-
private CharSequence mButtonNeutralText;
-
private Message mButtonNeutralMessage;
private ScrollView mScrollView;
-
+
private int mIconId = 0;
-
private Drawable mIcon;
-
+
private ImageView mIconView;
-
private TextView mTitleView;
-
private TextView mMessageView;
-
private View mCustomTitleView;
-
+
private boolean mForceInverseBackground;
-
+
private ListAdapter mAdapter;
-
+
private int mCheckedItem = -1;
private int mAlertDialogLayout;
@@ -130,7 +113,7 @@
private int mListItemLayout;
private int mButtonPanelLayoutHint = AlertDialog.LAYOUT_HINT_NONE;
-
+
private Handler mHandler;
private final View.OnClickListener mButtonHandler = new View.OnClickListener() {
@@ -160,7 +143,7 @@
private static final class ButtonHandler extends Handler {
// Button clicks have Message.what as the BUTTON{1,2,3} constant
private static final int MSG_DISMISS_DIALOG = 1;
-
+
private WeakReference<DialogInterface> mDialog;
public ButtonHandler(DialogInterface dialog) {
@@ -170,13 +153,13 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
-
+
case DialogInterface.BUTTON_POSITIVE:
case DialogInterface.BUTTON_NEGATIVE:
case DialogInterface.BUTTON_NEUTRAL:
((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what);
break;
-
+
case MSG_DISMISS_DIALOG:
((DialogInterface) msg.obj).dismiss();
}
@@ -220,16 +203,16 @@
a.recycle();
}
-
+
static boolean canTextInput(View v) {
if (v.onCheckIsTextEditor()) {
return true;
}
-
+
if (!(v instanceof ViewGroup)) {
return false;
}
-
+
ViewGroup vg = (ViewGroup)v;
int i = vg.getChildCount();
while (i > 0) {
@@ -239,10 +222,10 @@
return true;
}
}
-
+
return false;
}
-
+
public void installContent() {
/* We use a custom title so never request a window title */
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
@@ -262,7 +245,7 @@
// TODO: use layout hint side for long messages/lists
return mAlertDialogLayout;
}
-
+
public void setTitle(CharSequence title) {
mTitle = title;
if (mTitleView != null) {
@@ -276,7 +259,7 @@
public void setCustomTitle(View customTitleView) {
mCustomTitleView = customTitleView;
}
-
+
public void setMessage(CharSequence message) {
mMessage = message;
if (mMessageView != null) {
@@ -301,7 +284,7 @@
mViewLayoutResId = 0;
mViewSpacingSpecified = false;
}
-
+
/**
* Set the view to display in the dialog along with the spacing around that view
*/
@@ -326,7 +309,7 @@
/**
* Sets a click listener or a message to be sent when the button is clicked.
* You only need to pass one of {@code listener} or {@code msg}.
- *
+ *
* @param whichButton Which button, can be one of
* {@link DialogInterface#BUTTON_POSITIVE},
* {@link DialogInterface#BUTTON_NEGATIVE}, or
@@ -341,24 +324,24 @@
if (msg == null && listener != null) {
msg = mHandler.obtainMessage(whichButton, listener);
}
-
+
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
mButtonPositiveText = text;
mButtonPositiveMessage = msg;
break;
-
+
case DialogInterface.BUTTON_NEGATIVE:
mButtonNegativeText = text;
mButtonNegativeMessage = msg;
break;
-
+
case DialogInterface.BUTTON_NEUTRAL:
mButtonNeutralText = text;
mButtonNeutralMessage = msg;
break;
-
+
default:
throw new IllegalArgumentException("Button does not exist");
}
@@ -416,11 +399,11 @@
public void setInverseBackgroundForced(boolean forceInverseBackground) {
mForceInverseBackground = forceInverseBackground;
}
-
+
public ListView getListView() {
return mListView;
}
-
+
public Button getButton(int whichButton) {
switch (whichButton) {
case DialogInterface.BUTTON_POSITIVE:
@@ -433,7 +416,7 @@
return null;
}
}
-
+
@SuppressWarnings({"UnusedDeclaration"})
public boolean onKeyDown(int keyCode, KeyEvent event) {
return mScrollView != null && mScrollView.executeKeyEvent(event);
@@ -469,12 +452,12 @@
final LinearLayout contentPanel = (LinearLayout) mWindow.findViewById(R.id.contentPanel);
setupContent(contentPanel);
final boolean hasButtons = setupButtons();
-
+
final LinearLayout topPanel = (LinearLayout) mWindow.findViewById(R.id.topPanel);
final TypedArray a = mContext.obtainStyledAttributes(
null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
final boolean hasTitle = setupTitle(topPanel);
-
+
final View buttonPanel = mWindow.findViewById(R.id.buttonPanel);
if (!hasButtons) {
buttonPanel.setVisibility(View.GONE);
@@ -536,14 +519,14 @@
private boolean setupTitle(LinearLayout topPanel) {
boolean hasTitle = true;
-
+
if (mCustomTitleView != null) {
// Add the custom title view directly to the topPanel layout
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
-
+
topPanel.addView(mCustomTitleView, 0, lp);
-
+
// Hide the title template
View titleTemplate = mWindow.findViewById(R.id.title_template);
titleTemplate.setVisibility(View.GONE);
@@ -587,19 +570,19 @@
private void setupContent(LinearLayout contentPanel) {
mScrollView = (ScrollView) mWindow.findViewById(R.id.scrollView);
mScrollView.setFocusable(false);
-
+
// Special case for users that only want to display a String
mMessageView = (TextView) mWindow.findViewById(R.id.message);
if (mMessageView == null) {
return;
}
-
+
if (mMessage != null) {
mMessageView.setText(mMessage);
} else {
mMessageView.setVisibility(View.GONE);
mScrollView.removeView(mMessageView);
-
+
if (mListView != null) {
contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
contentPanel.addView(mListView,
@@ -664,7 +647,7 @@
centerButton(mButtonNeutral);
}
}
-
+
return whichButtons != 0;
}
@@ -694,7 +677,12 @@
int centerBright = 0;
int bottomBright = 0;
int bottomMedium = 0;
- if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.KITKAT) {
+
+ // If the needsDefaultBackgrounds attribute is set, we know we're
+ // inheriting from a framework style.
+ final boolean needsDefaultBackgrounds = a.getBoolean(
+ R.styleable.AlertDialog_needsDefaultBackgrounds, true);
+ if (needsDefaultBackgrounds) {
fullDark = R.drawable.popup_full_dark;
topDark = R.drawable.popup_top_dark;
centerDark = R.drawable.popup_center_dark;
@@ -705,12 +693,12 @@
bottomBright = R.drawable.popup_bottom_bright;
bottomMedium = R.drawable.popup_bottom_medium;
}
+
topBright = a.getResourceId(R.styleable.AlertDialog_topBright, topBright);
topDark = a.getResourceId(R.styleable.AlertDialog_topDark, topDark);
centerBright = a.getResourceId(R.styleable.AlertDialog_centerBright, centerBright);
centerDark = a.getResourceId(R.styleable.AlertDialog_centerDark, centerDark);
-
/* We now set the background of all of the sections of the alert.
* First collect together each section that is being displayed along
* with whether it is on a light or dark background, then run through
@@ -789,31 +777,6 @@
}
}
- /* TODO: uncomment section below. The logic for this should be if
- * it's a Contextual menu being displayed AND only a Cancel button
- * is shown then do this.
- */
-// if (hasButtons && (mListView != null)) {
-
- /* Yet another *special* case. If there is a ListView with buttons
- * don't put the buttons on the bottom but instead put them in the
- * footer of the ListView this will allow more items to be
- * displayed.
- */
-
- /*
- contentPanel.setBackgroundResource(bottomBright);
- buttonPanel.setBackgroundResource(centerMedium);
- ViewGroup parent = (ViewGroup) mWindow.findViewById(R.id.parentPanel);
- parent.removeView(buttonPanel);
- AbsListView.LayoutParams params = new AbsListView.LayoutParams(
- AbsListView.LayoutParams.MATCH_PARENT,
- AbsListView.LayoutParams.MATCH_PARENT);
- buttonPanel.setLayoutParams(params);
- mListView.addFooterView(buttonPanel);
- */
-// }
-
final ListView listView = mListView;
if (listView != null && mAdapter != null) {
listView.setAdapter(mAdapter);
@@ -854,7 +817,7 @@
public static class AlertParams {
public final Context mContext;
public final LayoutInflater mInflater;
-
+
public int mIconId = 0;
public Drawable mIcon;
public int mIconAttrId = 0;
@@ -899,20 +862,20 @@
* will be bound to an adapter.
*/
public interface OnPrepareListViewListener {
-
+
/**
* Called before the ListView is bound to an adapter.
* @param listView The ListView that will be shown in the dialog.
*/
void onPrepareListView(ListView listView);
}
-
+
public AlertParams(Context context) {
mContext = context;
mCancelable = true;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
-
+
public void apply(AlertController dialog) {
if (mCustomTitleView != null) {
dialog.setCustomTitle(mCustomTitleView);
@@ -972,12 +935,12 @@
}
*/
}
-
+
private void createListView(final AlertController dialog) {
final RecycleListView listView = (RecycleListView)
mInflater.inflate(dialog.mListLayout, null);
ListAdapter adapter;
-
+
if (mIsMultiChoice) {
if (mCursor == null) {
adapter = new ArrayAdapter<CharSequence>(
@@ -1012,37 +975,37 @@
listView.setItemChecked(cursor.getPosition(),
cursor.getInt(mIsCheckedIndex) == 1);
}
-
+
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(dialog.mMultiChoiceItemLayout,
parent, false);
}
-
+
};
}
} else {
- int layout = mIsSingleChoice
+ int layout = mIsSingleChoice
? dialog.mSingleChoiceItemLayout : dialog.mListItemLayout;
if (mCursor == null) {
adapter = (mAdapter != null) ? mAdapter
: new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
} else {
- adapter = new SimpleCursorAdapter(mContext, layout,
+ adapter = new SimpleCursorAdapter(mContext, layout,
mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
}
}
-
+
if (mOnPrepareListViewListener != null) {
mOnPrepareListViewListener.onPrepareListView(listView);
}
-
+
/* Don't directly set the adapter on the ListView as we might
* want to add a footer to the ListView later.
*/
dialog.mAdapter = adapter;
dialog.mCheckedItem = mCheckedItem;
-
+
if (mOnClickListener != null) {
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
@@ -1065,12 +1028,12 @@
}
});
}
-
+
// Attach a given OnItemSelectedListener to the ListView
if (mOnItemSelectedListener != null) {
listView.setOnItemSelectedListener(mOnItemSelectedListener);
}
-
+
if (mIsSingleChoice) {
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
} else if (mIsMultiChoice) {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index b6e7353..107e8c6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -90,7 +90,7 @@
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
private boolean mShowExtended;
- private GridView mGridView;
+ private ListView mListView;
private Button mAlwaysButton;
private Button mOnceButton;
private int mIconDpi;
@@ -228,10 +228,13 @@
mLaunchedFromUid, alwaysUseOption);
final int layoutId;
+ final boolean useHeader;
if (mAdapter.hasFilteredItem()) {
layoutId = R.layout.resolver_list_with_default;
alwaysUseOption = false;
+ useHeader = true;
} else {
+ useHeader = false;
layoutId = R.layout.resolver_list;
}
mAlwaysUseOption = alwaysUseOption;
@@ -243,16 +246,19 @@
return;
} else if (count > 1) {
setContentView(layoutId);
- mGridView = (GridView) findViewById(R.id.resolver_list);
- mGridView.setAdapter(mAdapter);
- mGridView.setOnItemClickListener(this);
- mGridView.setOnItemLongClickListener(new ItemLongClickListener());
+ mListView = (ListView) findViewById(R.id.resolver_list);
+ mListView.setAdapter(mAdapter);
+ mListView.setOnItemClickListener(this);
+ mListView.setOnItemLongClickListener(new ItemLongClickListener());
if (alwaysUseOption) {
- mGridView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
- resizeGrid();
+ if (useHeader) {
+ mListView.addHeaderView(LayoutInflater.from(this).inflate(
+ R.layout.resolver_different_item_header, mListView, false));
+ }
} else if (count == 1) {
safelyStartActivity(mAdapter.intentForPosition(0, false));
mPackageMonitor.unregister();
@@ -265,8 +271,8 @@
final TextView empty = (TextView) findViewById(R.id.empty);
empty.setVisibility(View.VISIBLE);
- mGridView = (GridView) findViewById(R.id.resolver_list);
- mGridView.setVisibility(View.GONE);
+ mListView = (ListView) findViewById(R.id.resolver_list);
+ mListView.setVisibility(View.GONE);
}
final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel);
@@ -340,11 +346,6 @@
}
}
- void resizeGrid() {
- final int itemCount = mAdapter.getCount();
- mGridView.setNumColumns(Math.min(itemCount, mMaxColumns));
- }
-
void dismiss() {
if (!isFinishing()) {
finish();
@@ -419,19 +420,24 @@
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (mAlwaysUseOption) {
- final int checkedPos = mGridView.getCheckedItemPosition();
+ final int checkedPos = mListView.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
mLastSelected = checkedPos;
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGridView.setSelection(checkedPos);
+ mListView.setSelection(checkedPos);
}
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ position -= mListView.getHeaderViewsCount();
+ if (position < 0) {
+ // Header views don't count.
+ return;
+ }
ResolveInfo resolveInfo = mAdapter.resolveInfoForPosition(position, true);
if (mResolvingHome && hasManagedProfile()
&& !supportsManagedProfiles(resolveInfo)) {
@@ -441,13 +447,13 @@
Toast.LENGTH_LONG).show();
return;
}
- final int checkedPos = mGridView.getCheckedItemPosition();
+ final int checkedPos = mListView.getCheckedItemPosition();
final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
mOnceButton.setEnabled(hasValidSelection);
if (hasValidSelection) {
- mGridView.smoothScrollToPosition(checkedPos);
+ mListView.smoothScrollToPosition(checkedPos);
}
mLastSelected = checkedPos;
} else {
@@ -504,7 +510,7 @@
public void onButtonClick(View v) {
final int id = v.getId();
startSelected(mAlwaysUseOption ?
- mGridView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
+ mListView.getCheckedItemPosition() : mAdapter.getFilteredPosition(),
id == R.id.button_always,
mAlwaysUseOption);
dismiss();
@@ -714,8 +720,6 @@
if (newItemCount == 0) {
// We no longer have any items... just finish the activity.
finish();
- } else if (newItemCount != oldItemCount) {
- resizeGrid();
}
}
@@ -957,19 +961,13 @@
}
public View getView(int position, View convertView, ViewGroup parent) {
- View view;
- if (convertView == null) {
+ View view = convertView;
+ if (view == null) {
view = mInflater.inflate(
com.android.internal.R.layout.resolve_list_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
view.setTag(holder);
-
- // Fix the icon size even if we have different sized resources
- ViewGroup.LayoutParams lp = holder.icon.getLayoutParams();
- lp.width = lp.height = mIconSize;
- } else {
- view = convertView;
}
bindView(view, getItem(position));
return view;
@@ -1007,6 +1005,11 @@
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ position -= mListView.getHeaderViewsCount();
+ if (position < 0) {
+ // Header views don't count.
+ return false;
+ }
ResolveInfo ri = mAdapter.resolveInfoForPosition(position, true);
showAppDetails(ri);
return true;
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 6f1c7ec..99c87ea 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -35,6 +35,7 @@
import android.widget.Toolbar;
import com.android.internal.R;
import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPresenter;
import com.android.internal.widget.DecorToolbar;
import com.android.internal.widget.ToolbarWidgetWrapper;
@@ -45,6 +46,7 @@
private DecorToolbar mDecorToolbar;
private boolean mToolbarMenuPrepared;
private Window.Callback mWindowCallback;
+ private boolean mMenuCallbackSet;
private CharSequence mHomeDescription;
@@ -453,6 +455,10 @@
}
void populateOptionsMenu() {
+ if (!mMenuCallbackSet) {
+ mToolbar.setMenuCallbacks(new ActionMenuPresenterCallback(), new MenuBuilderCallback());
+ mMenuCallbackSet = true;
+ }
final Menu menu = mToolbar.getMenu();
final MenuBuilder mb = menu instanceof MenuBuilder ? (MenuBuilder) menu : null;
if (mb != null) {
@@ -514,4 +520,51 @@
return result;
}
}
+
+ private final class ActionMenuPresenterCallback implements MenuPresenter.Callback {
+ private boolean mClosingActionMenu;
+
+ @Override
+ public boolean onOpenSubMenu(MenuBuilder subMenu) {
+ if (mWindowCallback != null) {
+ mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, subMenu);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+ if (mClosingActionMenu) {
+ return;
+ }
+
+ mClosingActionMenu = true;
+ mToolbar.dismissPopupMenus();
+ if (mWindowCallback != null) {
+ mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+ }
+ mClosingActionMenu = false;
+ }
+ }
+
+ private final class MenuBuilderCallback implements MenuBuilder.Callback {
+
+ @Override
+ public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+ return false;
+ }
+
+ @Override
+ public void onMenuModeChange(MenuBuilder menu) {
+ if (mWindowCallback != null) {
+ if (mToolbar.isOverflowMenuShowing()) {
+ mWindowCallback.onPanelClosed(Window.FEATURE_ACTION_BAR, menu);
+ } else if (mWindowCallback.onPreparePanel(Window.FEATURE_OPTIONS_PANEL,
+ null, menu)) {
+ mWindowCallback.onMenuOpened(Window.FEATURE_ACTION_BAR, menu);
+ }
+ }
+ }
+ }
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c17f4ee..7bdb4be 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -390,7 +390,10 @@
if (!emulated && (checkBoth || prefer == RECOMMEND_INSTALL_EXTERNAL)) {
final File target = new UserEnvironment(UserHandle.USER_OWNER)
.getExternalStorageDirectory();
- fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+ // External is only an option when size is known
+ if (sizeBytes > 0) {
+ fitsOnExternal = (sizeBytes <= storage.getStorageBytesUntilLow(target));
+ }
}
if (prefer == RECOMMEND_INSTALL_INTERNAL) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 69cdbff..45a9dde 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -94,7 +94,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 113 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 114 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -385,10 +385,9 @@
String mLastWakeupReason = null;
long mLastWakeupUptimeMs = 0;
- private final HashMap<String, LongSamplingCounter> mWakeupReasonStats =
- new HashMap<String, LongSamplingCounter>();
+ private final HashMap<String, SamplingTimer> mWakeupReasonStats = new HashMap<>();
- public Map<String, ? extends LongCounter> getWakeupReasonStats() {
+ public Map<String, ? extends Timer> getWakeupReasonStats() {
return mWakeupReasonStats;
}
@@ -1131,6 +1130,10 @@
mCurrentReportedCount = count;
}
+ public void addCurrentReportedCount(int delta) {
+ updateCurrentReportedCount(mCurrentReportedCount + delta);
+ }
+
public void updateCurrentReportedTotalTime(long totalTime) {
if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) {
// Updating the reported value for the first time.
@@ -1141,6 +1144,10 @@
mCurrentReportedTotalTime = totalTime;
}
+ public void addCurrentReportedTotalTime(long delta) {
+ updateCurrentReportedTotalTime(mCurrentReportedTotalTime + delta);
+ }
+
public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime);
if (mTrackingReportedValues) {
@@ -1688,13 +1695,13 @@
* Get the wakeup reason counter, and create a new one if one
* doesn't already exist.
*/
- public LongSamplingCounter getWakeupReasonCounterLocked(String name) {
- LongSamplingCounter counter = mWakeupReasonStats.get(name);
- if (counter == null) {
- counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
- mWakeupReasonStats.put(name, counter);
+ public SamplingTimer getWakeupReasonTimerLocked(String name) {
+ SamplingTimer timer = mWakeupReasonStats.get(name);
+ if (timer == null) {
+ timer = new SamplingTimer(mOnBatteryTimeBase, true);
+ mWakeupReasonStats.put(name, timer);
}
- return counter;
+ return timer;
}
private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
@@ -2753,8 +2760,9 @@
void aggregateLastWakeupUptimeLocked(long uptimeMs) {
if (mLastWakeupReason != null) {
long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
- LongSamplingCounter timer = getWakeupReasonCounterLocked(mLastWakeupReason);
- timer.addCountLocked(deltaUptime);
+ SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason);
+ timer.addCurrentReportedCount(1);
+ timer.addCurrentReportedTotalTime(deltaUptime * 1000); // time is in microseconds
mLastWakeupReason = null;
}
}
@@ -2762,7 +2770,7 @@
public void noteWakeupReasonLocked(String reason) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
- if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason reason \"" + reason +"\": "
+ if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": "
+ Integer.toHexString(mHistoryCur.states));
aggregateLastWakeupUptimeLocked(uptime);
mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag;
@@ -6193,7 +6201,7 @@
}
public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
- StopwatchTimer t = mJobStats.stopObject(name);
+ StopwatchTimer t = mJobStats.startObject(name);
if (t != null) {
t.startRunningLocked(elapsedRealtimeMs);
}
@@ -6636,8 +6644,8 @@
}
if (mWakeupReasonStats.size() > 0) {
- for (LongSamplingCounter timer : mWakeupReasonStats.values()) {
- mOnBatteryScreenOffTimeBase.remove(timer);
+ for (SamplingTimer timer : mWakeupReasonStats.values()) {
+ mOnBatteryTimeBase.remove(timer);
}
mWakeupReasonStats.clear();
}
@@ -7848,7 +7856,7 @@
for (int iwr = 0; iwr < NWR; iwr++) {
if (in.readInt() != 0) {
String reasonName = in.readString();
- getWakeupReasonCounterLocked(reasonName).readSummaryFromParcelLocked(in);
+ getWakeupReasonTimerLocked(reasonName).readSummaryFromParcelLocked(in);
}
}
@@ -8122,12 +8130,12 @@
}
out.writeInt(mWakeupReasonStats.size());
- for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
- LongSamplingCounter counter = ent.getValue();
- if (counter != null) {
+ for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
+ SamplingTimer timer = ent.getValue();
+ if (timer != null) {
out.writeInt(1);
out.writeString(ent.getKey());
- counter.writeSummaryFromParcelLocked(out);
+ timer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
} else {
out.writeInt(0);
}
@@ -8438,7 +8446,7 @@
for (int ikw = 0; ikw < NKW; ikw++) {
if (in.readInt() != 0) {
String wakelockName = in.readString();
- SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in);
+ SamplingTimer kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, in);
mKernelWakelockStats.put(wakelockName, kwlt);
}
}
@@ -8448,9 +8456,8 @@
for (int iwr = 0; iwr < NWR; iwr++) {
if (in.readInt() != 0) {
String reasonName = in.readString();
- LongSamplingCounter counter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase,
- in);
- mWakeupReasonStats.put(reasonName, counter);
+ SamplingTimer timer = new SamplingTimer(mOnBatteryTimeBase, in);
+ mWakeupReasonStats.put(reasonName, timer);
}
}
@@ -8585,12 +8592,12 @@
}
}
out.writeInt(mWakeupReasonStats.size());
- for (Map.Entry<String, LongSamplingCounter> ent : mWakeupReasonStats.entrySet()) {
- LongSamplingCounter counter = ent.getValue();
- if (counter != null) {
+ for (Map.Entry<String, SamplingTimer> ent : mWakeupReasonStats.entrySet()) {
+ SamplingTimer timer = ent.getValue();
+ if (timer != null) {
out.writeInt(1);
out.writeString(ent.getKey());
- counter.writeToParcel(out);
+ timer.writeToParcel(out, uSecRealtime);
} else {
out.writeInt(0);
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 54c532a..c579a15 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -20,9 +20,12 @@
import dalvik.system.ZygoteHooks;
import android.system.ErrnoException;
import android.system.Os;
+import android.os.SystemClock;
+import android.util.Slog;
/** @hide */
public final class Zygote {
+ private static final String TAG = "Zygote";
/*
* Bit values for "debugFlags" argument. The definitions are duplicated
* in the native code.
@@ -75,21 +78,41 @@
* file descriptor numbers that are to be closed by the child
* (and replaced by /dev/null) after forking. An integer value
* of -1 in any entry in the array means "ignore this one".
+ * @param instructionSet null-ok the instruction set to use.
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
- int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+ String instructionSet) {
+ long startTime = SystemClock.elapsedRealtime();
VM_HOOKS.preFork();
+ checkTime(startTime, "Zygote.preFork");
int pid = nativeForkAndSpecialize(
- uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
+ instructionSet);
+ checkTime(startTime, "Zygote.nativeForkAndSpecialize");
VM_HOOKS.postForkCommon();
+ checkTime(startTime, "Zygote.postForkCommon");
return pid;
}
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
- int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+ String instructionSet);
+
+ /**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private static void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
/**
* Special method to start the system server process. In addition to the
@@ -126,8 +149,10 @@
native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
- private static void callPostForkChildHooks(int debugFlags) {
- VM_HOOKS.postForkChild(debugFlags);
+ private static void callPostForkChildHooks(int debugFlags, String instructionSet) {
+ long startTime = SystemClock.elapsedRealtime();
+ VM_HOOKS.postForkChild(debugFlags, instructionSet);
+ checkTime(startTime, "Zygote.callPostForkChildHooks");
}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 43ebb3d..fb50b25 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -37,6 +37,8 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import libcore.io.IoUtils;
+import android.os.SystemClock;
+import android.util.Slog;
/**
* A connection that can make spawn requests.
@@ -103,11 +105,23 @@
}
/**
+ * Temporary hack: check time since start time and log if over a fixed threshold.
+ *
+ */
+ private void checkTime(long startTime, String where) {
+ long now = SystemClock.elapsedRealtime();
+ if ((now-startTime) > 1000) {
+ // If we are taking more than a second, log about it.
+ Slog.w(TAG, "Slow operation: " + (now-startTime) + "ms so far, now at " + where);
+ }
+ }
+
+ /**
* Returns the file descriptor of the associated socket.
*
* @return null-ok; file descriptor
*/
- FileDescriptor getFileDesciptor() {
+ FileDescriptor getFileDescriptor() {
return mSocket.getFileDescriptor();
}
@@ -131,6 +145,8 @@
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
+ long startTime = SystemClock.elapsedRealtime();
+
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
@@ -140,6 +156,7 @@
return true;
}
+ checkTime(startTime, "zygoteConnection.runOnce: readArgumentList");
if (args == null) {
// EOF reached.
closeSocket();
@@ -171,14 +188,19 @@
", effective=0x" + Long.toHexString(parsedArgs.effectiveCapabilities));
}
+
applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
+ checkTime(startTime, "zygoteConnection.runOnce: apply security policies");
+
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
@@ -220,9 +242,11 @@
fd = null;
+ checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize");
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName, fdsToClose);
+ parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet);
+ checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize");
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
@@ -311,6 +335,7 @@
* [--] <args for RuntimeInit >
* <li> If <code>--runtime-init</code> is absent:
* [--] <classname> [args...]
+ * <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate.
* </ul>
*/
static class Arguments {
@@ -374,6 +399,11 @@
boolean abiListQuery;
/**
+ * The instruction set to use, or null when not important.
+ */
+ String instructionSet;
+
+ /**
* Constructs instance and parses args
* @param args zygote command-line args
* @throws IllegalArgumentException
@@ -528,6 +558,8 @@
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else if (arg.equals("--query-abi-list")) {
abiListQuery = true;
+ } else if (arg.startsWith("--instruction-set=")) {
+ instructionSet = arg.substring(arg.indexOf('=') + 1);
} else {
break;
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 051de6e..0aee0e3 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -770,7 +770,7 @@
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
+ fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
diff --git a/core/java/com/android/internal/util/ParcelableString.java b/core/java/com/android/internal/util/ParcelableString.java
new file mode 100644
index 0000000..6bd856f
--- /dev/null
+++ b/core/java/com/android/internal/util/ParcelableString.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Helper class to adapt a simple String to cases where a Parcelable is expected.
+ * @hide
+ */
+public class ParcelableString implements Parcelable {
+ public String string;
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(string);
+ }
+
+ public static final Parcelable.Creator<ParcelableString> CREATOR =
+ new Parcelable.Creator<ParcelableString>() {
+ @Override
+ public ParcelableString createFromParcel(Parcel in) {
+ ParcelableString ret = new ParcelableString();
+ ret.string = in.readString();
+ return ret;
+ }
+ @Override
+ public ParcelableString[] newArray(int size) {
+ return new ParcelableString[size];
+ }
+ };
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 7db70ba..45d790b 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -1440,6 +1440,16 @@
return Boolean.parseBoolean(value);
}
+ public static boolean readBooleanAttribute(XmlPullParser in, String name,
+ boolean defaultValue) {
+ final String value = in.getAttributeValue(null, name);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ return Boolean.parseBoolean(value);
+ }
+ }
+
public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
throws IOException {
out.attribute(null, name, Boolean.toString(value));
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index c7ac815..062a9b1 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -59,6 +59,7 @@
private int mSubtitleStyleRes;
private Drawable mSplitBackground;
private boolean mTitleOptional;
+ private int mCloseItemLayout;
private Animator mCurrentAnimation;
private boolean mAnimateInOnLayout;
@@ -99,6 +100,10 @@
mSplitBackground = a.getDrawable(
com.android.internal.R.styleable.ActionMode_backgroundSplit);
+ mCloseItemLayout = a.getResourceId(
+ com.android.internal.R.styleable.ActionMode_closeItemLayout,
+ R.layout.action_mode_close_item);
+
a.recycle();
}
@@ -120,7 +125,7 @@
LayoutParams.MATCH_PARENT);
if (!split) {
mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
- mMenuView.setBackgroundDrawable(null);
+ mMenuView.setBackground(null);
final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
if (oldParent != null) oldParent.removeView(mMenuView);
addView(mMenuView, layoutParams);
@@ -134,7 +139,7 @@
layoutParams.width = LayoutParams.MATCH_PARENT;
layoutParams.height = mContentHeight;
mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
- mMenuView.setBackgroundDrawable(mSplitBackground);
+ mMenuView.setBackground(mSplitBackground);
final ViewGroup oldParent = (ViewGroup) mMenuView.getParent();
if (oldParent != null) oldParent.removeView(mMenuView);
mSplitView.addView(mMenuView, layoutParams);
@@ -211,7 +216,7 @@
public void initForMode(final ActionMode mode) {
if (mClose == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
- mClose = inflater.inflate(R.layout.action_mode_close_item, this, false);
+ mClose = inflater.inflate(mCloseItemLayout, this, false);
addView(mClose);
} else if (mClose.getParent() == null) {
addView(mClose);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2114ff6..c84708e 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1449,7 +1449,7 @@
}
int textId;
- if (getTelecommManager().isInCall()) {
+ if (isInCall()) {
// show "return to call" text and show phone icon
textId = R.string.lockscreen_return_to_call;
int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
@@ -1470,6 +1470,13 @@
getTelecommManager().showInCallScreen(false);
}
+ /**
+ * @return {@code true} if there is a call currently in progress, {@code false} otherwise.
+ */
+ public boolean isInCall() {
+ return getTelecommManager().isInCall();
+ }
+
private TelecommManager getTelecommManager() {
return (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index e53f9dd..375822f 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -20,15 +20,15 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
@@ -68,6 +68,7 @@
private boolean mIsDragging;
private boolean mOpenOnClick;
+ private boolean mOpenOnLayout;
private final int mTouchSlop;
private final float mMinFlingVelocity;
private final OverScroller mScroller;
@@ -202,6 +203,8 @@
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
+ mVelocityTracker.addMovement(ev);
+
boolean handled = false;
switch (action) {
case MotionEvent.ACTION_DOWN: {
@@ -288,6 +291,10 @@
break;
case MotionEvent.ACTION_CANCEL: {
+ if (mIsDragging) {
+ smoothScrollTo(
+ mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ }
resetTouch();
return true;
}
@@ -498,28 +505,39 @@
@Override
public void onStopNestedScroll(View child) {
super.onStopNestedScroll(child);
- smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ if (mScroller.isFinished()) {
+ smoothScrollTo(mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0);
+ }
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
int dxUnconsumed, int dyUnconsumed) {
- if (dyUnconsumed > 0) {
+ if (dyUnconsumed < 0) {
performDrag(-dyUnconsumed);
}
}
@Override
public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
- if (dy < 0) {
- consumed[1] = (int) performDrag(-dy);
+ if (dy > 0) {
+ consumed[1] = (int) -performDrag(-dy);
}
}
@Override
+ public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
+ if (velocityY > mMinFlingVelocity && mCollapseOffset != 0) {
+ smoothScrollTo(0, velocityY);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) {
- smoothScrollTo(velocityY < 0 ? 0 : mCollapsibleHeight, velocityY);
+ smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY);
return true;
}
return false;
@@ -571,8 +589,8 @@
if (isLaidOut()) {
mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight);
} else {
- // Start out collapsed at first
- mCollapseOffset = mCollapsibleHeight;
+ // Start out collapsed at first unless we restored state for otherwise
+ mCollapseOffset = mOpenOnLayout ? 0 : mCollapsibleHeight;
}
mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset;
@@ -634,6 +652,20 @@
return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final SavedState ss = new SavedState(super.onSaveInstanceState());
+ ss.open = mCollapsibleHeight > 0 && mCollapseOffset == 0;
+ return ss;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ final SavedState ss = (SavedState) state;
+ super.onRestoreInstanceState(ss.getSuperState());
+ mOpenOnLayout = ss.open;
+ }
+
public static class LayoutParams extends MarginLayoutParams {
public boolean alwaysShow;
public boolean ignoreOffset;
@@ -670,4 +702,36 @@
super(source);
}
}
+
+ static class SavedState extends BaseSavedState {
+ boolean open;
+
+ SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ open = in.readInt() != 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(open ? 1 : 0);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+ @Override
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ @Override
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 2106d38..dbaa4b8 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -129,6 +129,7 @@
android/graphics/Xfermode.cpp \
android/graphics/YuvToJpegEncoder.cpp \
android/graphics/pdf/PdfDocument.cpp \
+ android/graphics/pdf/PdfEditor.cpp \
android/graphics/pdf/PdfRenderer.cpp \
android_media_AudioRecord.cpp \
android_media_AudioSystem.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 62d8036..a63258c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -126,6 +126,7 @@
extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
extern int register_android_graphics_Xfermode(JNIEnv* env);
extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
+extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env);
extern int register_android_graphics_pdf_PdfRenderer(JNIEnv* env);
extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
@@ -1305,6 +1306,7 @@
REG_JNI(register_android_graphics_Xfermode),
REG_JNI(register_android_graphics_YuvImage),
REG_JNI(register_android_graphics_pdf_PdfDocument),
+ REG_JNI(register_android_graphics_pdf_PdfEditor),
REG_JNI(register_android_graphics_pdf_PdfRenderer),
REG_JNI(register_android_database_CursorWindow),
diff --git a/core/jni/android/graphics/pdf/PdfEditor.cpp b/core/jni/android/graphics/pdf/PdfEditor.cpp
new file mode 100644
index 0000000..5f60c9e
--- /dev/null
+++ b/core/jni/android/graphics/pdf/PdfEditor.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "fpdfview.h"
+#include "fpdfedit.h"
+#include "fpdfsave.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <vector>
+#include <utils/Log.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android {
+
+static Mutex sLock;
+
+static int sUnmatchedInitRequestCount = 0;
+
+static void initializeLibraryIfNeeded() {
+ Mutex::Autolock _l(sLock);
+ if (sUnmatchedInitRequestCount == 0) {
+ FPDF_InitLibrary(NULL);
+ }
+ sUnmatchedInitRequestCount++;
+}
+
+static void destroyLibraryIfNeeded() {
+ Mutex::Autolock _l(sLock);
+ sUnmatchedInitRequestCount--;
+ if (sUnmatchedInitRequestCount == 0) {
+ FPDF_DestroyLibrary();
+ }
+}
+
+static int getBlock(void* param, unsigned long position, unsigned char* outBuffer,
+ unsigned long size) {
+ const int fd = reinterpret_cast<intptr_t>(param);
+ const int readCount = pread(fd, outBuffer, size, position);
+ if (readCount < 0) {
+ ALOGE("Cannot read from file descriptor. Error:%d", errno);
+ return 0;
+ }
+ return 1;
+}
+
+static jlong nativeOpen(JNIEnv* env, jclass thiz, jint fd, jlong size) {
+ initializeLibraryIfNeeded();
+
+ FPDF_FILEACCESS loader;
+ loader.m_FileLen = size;
+ loader.m_Param = reinterpret_cast<void*>(intptr_t(fd));
+ loader.m_GetBlock = &getBlock;
+
+ FPDF_DOCUMENT document = FPDF_LoadCustomDocument(&loader, NULL);
+
+ if (!document) {
+ const long error = FPDF_GetLastError();
+ jniThrowException(env, "java/io/IOException",
+ "cannot create document. Error:" + error);
+ destroyLibraryIfNeeded();
+ return -1;
+ }
+
+ return reinterpret_cast<jlong>(document);
+}
+
+static void nativeClose(JNIEnv* env, jclass thiz, jlong documentPtr) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ FPDF_CloseDocument(document);
+ destroyLibraryIfNeeded();
+}
+
+static jint nativeGetPageCount(JNIEnv* env, jclass thiz, jlong documentPtr) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ return FPDF_GetPageCount(document);
+}
+
+static jint nativeRemovePage(JNIEnv* env, jclass thiz, jlong documentPtr, jint pageIndex) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ FPDFPage_Delete(document, pageIndex);
+ return FPDF_GetPageCount(document);
+}
+
+struct PdfToFdWriter : FPDF_FILEWRITE {
+ int dstFd;
+};
+
+static bool writeAllBytes(const int fd, const void* buffer, const size_t byteCount) {
+ char* writeBuffer = static_cast<char*>(const_cast<void*>(buffer));
+ size_t remainingBytes = byteCount;
+ while (remainingBytes > 0) {
+ ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes);
+ if (writtenByteCount == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+ "Error writing to buffer: %d", errno);
+ return false;
+ }
+ remainingBytes -= writtenByteCount;
+ writeBuffer += writtenByteCount;
+ }
+ return true;
+}
+
+static int writeBlock(FPDF_FILEWRITE* owner, const void* buffer, unsigned long size) {
+ const PdfToFdWriter* writer = reinterpret_cast<PdfToFdWriter*>(owner);
+ const bool success = writeAllBytes(writer->dstFd, buffer, size);
+ if (success < 0) {
+ ALOGE("Cannot write to file descriptor. Error:%d", errno);
+ return 0;
+ }
+ return 1;
+}
+
+static void nativeWrite(JNIEnv* env, jclass thiz, jlong documentPtr, jint fd) {
+ FPDF_DOCUMENT document = reinterpret_cast<FPDF_DOCUMENT>(documentPtr);
+ PdfToFdWriter writer;
+ writer.dstFd = fd;
+ writer.WriteBlock = &writeBlock;
+ const bool success = FPDF_SaveAsCopy(document, &writer, FPDF_NO_INCREMENTAL);
+ if (!success) {
+ jniThrowException(env, "java/io/IOException",
+ "cannot write to fd. Error:" + errno);
+ destroyLibraryIfNeeded();
+ }
+}
+
+static JNINativeMethod gPdfEditor_Methods[] = {
+ {"nativeOpen", "(IJ)J", (void*) nativeOpen},
+ {"nativeClose", "(J)V", (void*) nativeClose},
+ {"nativeGetPageCount", "(J)I", (void*) nativeGetPageCount},
+ {"nativeRemovePage", "(JI)I", (void*) nativeRemovePage},
+ {"nativeWrite", "(JI)V", (void*) nativeWrite}
+};
+
+int register_android_graphics_pdf_PdfEditor(JNIEnv* env) {
+ return android::AndroidRuntime::registerNativeMethods(
+ env, "android/graphics/pdf/PdfEditor", gPdfEditor_Methods,
+ NELEM(gPdfEditor_Methods));
+};
+
+};
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index f5eaf94..9b96320 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -35,7 +35,15 @@
extern "C" void free_malloc_leak_info(uint8_t* info);
+#define DDMS_HEADER_SIGNATURE 0x812345dd
+#define DDMS_VERSION 2
+
struct Header {
+#if defined(__LP64__)
+ uint32_t signature;
+ uint16_t version;
+ uint16_t pointerSize;
+#endif
size_t mapSize;
size_t allocSize;
size_t allocInfoSize;
@@ -77,6 +85,12 @@
ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
+#if defined(__LP64__)
+ header.signature = DDMS_HEADER_SIGNATURE;
+ header.version = DDMS_VERSION;
+ header.pointerSize = sizeof(void*);
+#endif
+
jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
if (array != NULL) {
env->SetByteArrayRegion(array, 0,
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index f0d7a35..7b33bc2 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -211,7 +211,7 @@
}
jobject jAudioFormat = NULL;
- if (event->trigger_in_data) {
+ if (event->trigger_in_data || event->capture_available) {
jAudioFormat = env->NewObject(gAudioFormatClass,
gAudioFormatCstor,
audioFormatFromNative(event->audio_config.format),
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 5faf03d..396f3ec 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1888,6 +1888,37 @@
return array;
}
+static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
+ jint styleId)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return NULL;
+ }
+ const ResTable& res(am->getResources());
+
+ const ResTable::bag_entry* startOfBag;
+ const ssize_t N = res.lockBag(styleId, &startOfBag);
+ if (N < 0) {
+ return NULL;
+ }
+
+ jintArray array = env->NewIntArray(N);
+ if (array == NULL) {
+ res.unlockBag(startOfBag);
+ return NULL;
+ }
+
+ Res_value value;
+ const ResTable::bag_entry* bag = startOfBag;
+ for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
+ int resourceId = bag->map.name.ident;
+ env->SetIntArrayRegion(array, i, 1, &resourceId);
+ }
+ res.unlockBag(startOfBag);
+ return array;
+}
+
static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
{
if (isSystem) {
@@ -2038,6 +2069,8 @@
(void*) android_content_AssetManager_getArrayStringInfo },
{ "getArrayIntResource","(I)[I",
(void*) android_content_AssetManager_getArrayIntResource },
+ { "getStyleAttributes","(I)[I",
+ (void*) android_content_AssetManager_getStyleAttributes },
// Bookkeeping.
{ "init", "(Z)V",
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 1296831..050037e 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -173,6 +173,12 @@
return true;
}
+static jboolean android_view_RenderNode_hasShadow(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().hasShadow();
+}
+
static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -458,7 +464,7 @@
static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- renderNode->animators().endAllAnimators();
+ renderNode->animators().endAllStagingAnimators();
}
#endif // USE_OPENGL_RENDERER
@@ -491,6 +497,7 @@
{ "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
{ "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
{ "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone },
+ { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow },
{ "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
{ "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index 85c2a09..84b7913 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -159,6 +159,11 @@
animator->setInterpolator(interpolator);
}
+static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) {
+ BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
+ animator->setAllowRunningAsync(mayRunAsync);
+}
+
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
if (finishListener) {
@@ -191,6 +196,7 @@
{ "nGetDuration", "(J)J", (void*) getDuration },
{ "nSetStartDelay", "(JJ)V", (void*) setStartDelay },
{ "nSetInterpolator", "(JJ)V", (void*) setInterpolator },
+ { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync },
{ "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start },
{ "nEnd", "(J)V", (void*) end },
#endif
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8f30f5d..06c22ae 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -117,7 +117,8 @@
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
+ jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
+ int rotation) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
@@ -131,17 +132,13 @@
SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient());
status_t res;
- if (width > 0 && height > 0) {
- if (allLayers) {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- useIdentityTransform);
- } else {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform);
- }
- } else {
- res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
+ if (allLayers) {
+ minLayer = 0;
+ maxLayer = -1UL;
}
+
+ res = screenshot->update(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
if (res != NO_ERROR) {
return NULL;
}
@@ -588,7 +585,7 @@
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
(void*)nativeScreenshot },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 6ec6b00..a8edb77 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -158,20 +158,17 @@
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
- virtual void startFrame() {
- mRootNode->doAttachAnimatingNodes(this);
- AnimationContext::startFrame();
+ virtual void startFrame(TreeInfo::TraversalMode mode) {
+ if (mode == TreeInfo::MODE_FULL) {
+ mRootNode->doAttachAnimatingNodes(this);
+ }
+ AnimationContext::startFrame(mode);
}
// Runs any animations still left in mCurrentFrameAnimations
virtual void runRemainingAnimations(TreeInfo& info) {
AnimationContext::runRemainingAnimations(info);
- // post all the finished stuff
- if (mOnFinishedEvents.size()) {
- sp<InvokeAnimationListeners> message
- = new InvokeAnimationListeners(mOnFinishedEvents);
- mRootNode->sendMessage(message);
- }
+ postOnFinishedEvents();
}
virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) {
@@ -179,9 +176,22 @@
mOnFinishedEvents.push_back(event);
}
+ virtual void destroy() {
+ AnimationContext::destroy();
+ postOnFinishedEvents();
+ }
+
private:
sp<RootRenderNode> mRootNode;
std::vector<OnFinishedEvent> mOnFinishedEvents;
+
+ void postOnFinishedEvents() {
+ if (mOnFinishedEvents.size()) {
+ sp<InvokeAnimationListeners> message
+ = new InvokeAnimationListeners(mOnFinishedEvents);
+ mRootNode->sendMessage(message);
+ }
+ }
};
class ContextFactoryImpl : public IContextFactory {
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index c84a466..2e2d0c7 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -175,17 +175,23 @@
continue;
}
}
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
- // Next field is tag.
- rawTag = strtoll(pos, &endPos, 16);
- //ALOGI("Index #%d: %s", idx, buffer);
- if (pos == endPos) {
- ALOGE("bad tag: %s", pos);
- fclose(fp);
- return -1;
+
+ // Ignore whitespace
+ while (*pos == ' ') pos++;
+
+ // Find end of tag field
+ endPos = pos;
+ while (*endPos != ' ') endPos++;
+
+ // Three digit field is always 0x0, otherwise parse
+ if (endPos - pos == 3) {
+ rawTag = 0;
+ } else {
+ if (sscanf(pos, "%llx", &rawTag) != 1) {
+ ALOGE("bad tag: %s", pos);
+ fclose(fp);
+ return -1;
+ }
}
s.tag = rawTag >> 32;
if (limitTag != -1 && s.tag != limitTag) {
@@ -193,10 +199,10 @@
continue;
}
pos = endPos;
- // Skip whitespace.
- while (*pos == ' ') {
- pos++;
- }
+
+ // Ignore whitespace
+ while (*pos == ' ') pos++;
+
// Parse remaining fields.
if (sscanf(pos, "%u %u %llu %llu %llu %llu",
&s.uid, &s.set, &s.rxBytes, &s.rxPackets,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 1f7acec..451d97a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -43,6 +43,7 @@
#include <utils/String8.h>
#include <selinux/android.h>
#include <processgroup/processgroup.h>
+#include <inttypes.h>
#include "android_runtime/AndroidRuntime.h"
#include "JNIHelp.h"
@@ -398,14 +399,33 @@
}
}
+ // Temporary timing check.
+uint64_t MsTime() {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return static_cast<uint64_t>(now.tv_sec) * UINT64_C(1000) + now.tv_nsec / UINT64_C(1000000);
+}
+
+
+void ckTime(uint64_t start, const char* where) {
+ uint64_t now = MsTime();
+ if ((now-start) > 1000) {
+ // If we are taking more than a second, log about it.
+ ALOGW("Slow operation: %"PRIu64" ms in %s", (uint64_t)(now-start), where);
+ }
+}
+
// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
- bool is_system_server, jintArray fdsToClose) {
+ bool is_system_server, jintArray fdsToClose,
+ jstring instructionSet) {
+ uint64_t start = MsTime();
SetSigChldHandler();
+ ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
pid_t pid = fork();
@@ -413,9 +433,12 @@
// The child process.
gMallocLeakZygoteChild = 1;
+
// Clean up any descriptors which must be closed immediately
DetachDescriptors(env, fdsToClose);
+ ckTime(start, "ForkAndSpecializeCommon:Fork and detach");
+
// Keep capabilities across UID change, unless we're staying root.
if (uid != 0) {
EnableKeepCapabilities(env);
@@ -518,7 +541,11 @@
UnsetSigChldHandler();
- env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ ckTime(start, "ForkAndSpecializeCommon:child process setup");
+
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
+ is_system_server ? NULL : instructionSet);
+ ckTime(start, "ForkAndSpecializeCommon:PostForkChildHooks returns");
if (env->ExceptionCheck()) {
ALOGE("Error calling post fork hooks.");
RuntimeAbort(env);
@@ -536,7 +563,7 @@
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
- jintArray fdsToClose) {
+ jintArray fdsToClose, jstring instructionSet) {
// Grant CAP_WAKE_ALARM to the Bluetooth process.
jlong capabilities = 0;
if (uid == AID_BLUETOOTH) {
@@ -545,7 +572,7 @@
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
- se_name, false, fdsToClose);
+ se_name, false, fdsToClose, instructionSet);
}
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -555,7 +582,7 @@
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
debug_flags, rlimits,
permittedCapabilities, effectiveCapabilities,
- MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+ MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL);
if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -573,7 +600,8 @@
}
static JNINativeMethod gMethods[] = {
- { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+ { "nativeForkAndSpecialize",
+ "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;)I",
(void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
(void *) com_android_internal_os_Zygote_nativeForkSystemServer }
@@ -584,7 +612,8 @@
if (gZygoteClass == NULL) {
RuntimeAbort(env);
}
- gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+ gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
+ "(ILjava/lang/String;)V");
return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
gMethods, NELEM(gMethods));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7c5233c..8a1d5af 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -182,11 +182,11 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
<protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
- <protected-broadcast android:name="android.intent.action.ANALOG_AUDIO_DOCK_PLUG" />
- <protected-broadcast android:name="android.intent.action.DIGITAL_AUDIO_DOCK_PLUG" />
- <protected-broadcast android:name="android.intent.action.HDMI_AUDIO_PLUG" />
- <protected-broadcast android:name="android.intent.action.USB_AUDIO_ACCESSORY_PLUG" />
- <protected-broadcast android:name="android.intent.action.USB_AUDIO_DEVICE_PLUG" />
+ <protected-broadcast android:name="android.media.action.ANALOG_AUDIO_DOCK_PLUG" />
+ <protected-broadcast android:name="android.media.action.DIGITAL_AUDIO_DOCK_PLUG" />
+ <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
+ <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" />
+ <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" />
<protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
<protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
@@ -2502,7 +2502,7 @@
<permission android:name="android.permission.PACKAGE_USAGE_STATS"
android:label="@string/permlab_pkgUsageStats"
android:description="@string/permdesc_pkgUsageStats"
- android:protectionLevel="signature|system|development|appop" />
+ android:protectionLevel="signature|development|appop" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<!-- @SystemApi Allows an application to collect battery statistics -->
diff --git a/core/res/res/drawable/ic_cab_done_material.xml b/core/res/res/drawable/emulator_circular_window_overlay.xml
similarity index 80%
rename from core/res/res/drawable/ic_cab_done_material.xml
rename to core/res/res/drawable/emulator_circular_window_overlay.xml
index a370288..7616b37 100644
--- a/core/res/res/drawable/ic_cab_done_material.xml
+++ b/core/res/res/drawable/emulator_circular_window_overlay.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_cab_done_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+<!-- Default to an empty shape drawable -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+</shape>
diff --git a/core/res/res/drawable/ic_cab_done_material.xml b/core/res/res/drawable/time_picker_header_material.xml
similarity index 77%
copy from core/res/res/drawable/ic_cab_done_material.xml
copy to core/res/res/drawable/time_picker_header_material.xml
index a370288..cdb92b6 100644
--- a/core/res/res/drawable/ic_cab_done_material.xml
+++ b/core/res/res/drawable/time_picker_header_material.xml
@@ -14,6 +14,9 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_cab_done_mtrl_alpha"
- android:tint="?attr/colorControlNormal" />
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlHighlight">
+ <item>
+ <color android:color="?attr/colorAccent" />
+ </item>
+</ripple>
diff --git a/core/res/res/layout-land/time_picker_holo.xml b/core/res/res/layout-land/time_picker_holo.xml
index f316f1b..ce90a5b 100644
--- a/core/res/res/layout-land/time_picker_holo.xml
+++ b/core/res/res/layout-land/time_picker_holo.xml
@@ -21,7 +21,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
- android:focusable="true"
android:layout_marginLeft="@dimen/timepicker_minimum_margin_sides"
android:layout_marginRight="@dimen/timepicker_minimum_margin_sides"
android:layout_marginTop="@dimen/timepicker_minimum_margin_top_bottom"
@@ -42,7 +41,5 @@
android:id="@+id/radial_picker"
android:layout_width="@dimen/timepicker_radial_picker_dimen"
android:layout_height="match_parent"
- android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true" />
+ android:layout_gravity="center" />
</LinearLayout>
diff --git a/core/res/res/layout/action_mode_close_item_material.xml b/core/res/res/layout/action_mode_close_item_material.xml
new file mode 100644
index 0000000..8eb780b
--- /dev/null
+++ b/core/res/res/layout/action_mode_close_item_material.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_mode_close_button"
+ android:focusable="true"
+ android:clickable="true"
+ android:paddingStart="8dip"
+ android:src="?android:attr/actionModeCloseDrawable"
+ style="?android:attr/actionModeCloseButtonStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginEnd="16dip" />
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 5f9066a..831ee98 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -33,8 +33,8 @@
android:gravity="center_vertical|start"
android:paddingStart="@dimen/alert_dialog_padding_material"
android:paddingEnd="@dimen/alert_dialog_padding_material"
- android:paddingTop="@dimen/alert_dialog_padding_material"
- android:paddingBottom="8dip">
+ android:paddingTop="@dimen/alert_dialog_padding_top_material"
+ android:paddingBottom="12dip">
<ImageView android:id="@+id/icon"
android:layout_width="32dip"
android:layout_height="32dip"
@@ -67,9 +67,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/alert_dialog_padding_material"
- android:paddingEnd="@dimen/alert_dialog_padding_material"
- android:paddingTop="@dimen/alert_dialog_padding_material"
- android:paddingBottom="@dimen/alert_dialog_padding_material" />
+ android:paddingEnd="@dimen/alert_dialog_padding_material" />
</ScrollView>
</LinearLayout>
@@ -77,7 +75,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:minHeight="64dp">
+ android:minHeight="48dp">
<FrameLayout android:id="@+id/custom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
@@ -89,15 +87,14 @@
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:orientation="horizontal"
- android:paddingStart="6dp"
- android:paddingEnd="6dp"
- android:paddingBottom="6dp">
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
<Button android:id="@+id/button3"
style="?attr/buttonBarNeutralButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
<Space
android:layout_width="0dp"
android:layout_height="0dp"
@@ -106,14 +103,10 @@
<Button android:id="@+id/button2"
style="?attr/buttonBarNegativeButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
<Button android:id="@+id/button1"
style="?attr/buttonBarPositiveButtonStyle"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="2"
- android:minHeight="@dimen/alert_dialog_button_bar_height" />
+ android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_progress_material.xml b/core/res/res/layout/alert_dialog_progress_material.xml
index b9d0814..bcf946f 100644
--- a/core/res/res/layout/alert_dialog_progress_material.xml
+++ b/core/res/res/layout/alert_dialog_progress_material.xml
@@ -17,32 +17,25 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:layout_height="match_parent">
- <ProgressBar android:id="@+id/progress"
- style="?android:attr/progressBarStyleHorizontal"
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material">
+ <ProgressBar
+ android:id="@+id/progress"
+ style="?attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:layout_marginBottom="1dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_centerHorizontal="true" />
<TextView
android:id="@+id/progress_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingBottom="16dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_alignParentStart="true"
android:layout_below="@id/progress" />
<TextView
android:id="@+id/progress_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingBottom="16dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
android:layout_alignParentEnd="true"
android:layout_below="@id/progress" />
</RelativeLayout>
diff --git a/core/res/res/layout/dialog_custom_title_material.xml b/core/res/res/layout/dialog_custom_title_material.xml
index 550b72e..248a05e 100644
--- a/core/res/res/layout/dialog_custom_title_material.xml
+++ b/core/res/res/layout/dialog_custom_title_material.xml
@@ -23,17 +23,17 @@
android:fitsSystemWindows="true">
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
- android:layout_height="?android:attr/windowTitleSize"
+ android:layout_height="?attr/windowTitleSize"
android:layout_weight="0"
android:gravity="center_vertical|start"
- style="?android:attr/windowTitleBackgroundStyle" />
+ style="?attr/windowTitleBackgroundStyle" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/dialog_title_icons_material.xml b/core/res/res/layout/dialog_title_icons_material.xml
index 28e20d9..21396da 100644
--- a/core/res/res/layout/dialog_title_icons_material.xml
+++ b/core/res/res/layout/dialog_title_icons_material.xml
@@ -28,16 +28,16 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip">
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_material">
<ImageView android:id="@+id/left_icon"
android:layout_width="32dip"
android:layout_height="32dip"
android:scaleType="fitCenter"
android:layout_marginEnd="8dip" />
- <TextView android:id="@android:id/title"
- style="?android:attr/windowTitleStyle"
+ <TextView android:id="@id/title"
+ style="?attr/windowTitleStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0" />
@@ -52,8 +52,8 @@
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/dialog_title_material.xml b/core/res/res/layout/dialog_title_material.xml
index 918c8f1..fcf6164 100644
--- a/core/res/res/layout/dialog_title_material.xml
+++ b/core/res/res/layout/dialog_title_material.xml
@@ -29,15 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:paddingTop="16dip" />
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material"
+ android:paddingTop="@dimen/alert_dialog_padding_top_material" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
- android:foreground="?android:attr/windowContentOverlay">
- <FrameLayout android:id="@android:id/content"
+ android:foreground="?attr/windowContentOverlay">
+ <FrameLayout android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 2382d18..8a66c3f 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -44,6 +44,7 @@
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
+ android:layout_marginEnd="8dp"
android:orientation="horizontal"
>
<TextView android:id="@+id/inbox_text0"
@@ -60,7 +61,6 @@
android:layout_height="@dimen/notification_badge_size"
android:layout_weight="0"
android:layout_marginStart="4dp"
- android:layout_marginEnd="8dp"
android:scaleType="fitCenter"
android:visibility="gone"
/>
diff --git a/core/res/res/layout/progress_dialog_material.xml b/core/res/res/layout/progress_dialog_material.xml
index 84d06b5..c6eb1f9 100644
--- a/core/res/res/layout/progress_dialog_material.xml
+++ b/core/res/res/layout/progress_dialog_material.xml
@@ -19,21 +19,25 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <LinearLayout android:id="@+id/body"
+ <LinearLayout
+ android:id="@+id/body"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
- android:padding="16dip">
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material">
- <ProgressBar android:id="@android:id/progress"
+ <ProgressBar
+ android:id="@id/progress"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:max="10000"
- android:layout_marginEnd="16dip" />
+ android:layout_marginEnd="16dp" />
- <TextView android:id="@+id/message"
+ <TextView
+ android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical" />
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 7aa9a72..37c4270 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -18,9 +18,10 @@
*/
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+ android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:minHeight="?attr/listPreferredItemHeightSmall"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:background="?attr/activatedBackgroundIndicator">
@@ -28,37 +29,40 @@
<!-- Activity icon when presenting dialog
Size will be filled in by ResolverActivity -->
<ImageView android:id="@+id/icon"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_gravity="center"
- android:layout_margin="4dp"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|center_vertical"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="12dp"
+ android:layout_marginBottom="12dp"
android:scaleType="fitCenter" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:gravity="center"
+ android:gravity="start|center_vertical"
android:orientation="vertical"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_gravity="center">
+ android:layout_gravity="start|center_vertical">
<!-- Activity name -->
<TextView android:id="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:fontFamily="sans-serif-condensed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2" />
+ android:textAppearance="?attr/textAppearanceMedium"
+ android:textColor="?attr/textColorPrimary"
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
<!-- Extended activity info to distinguish between duplicate activity names -->
<TextView android:id="@android:id/text2"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:fontFamily="sans-serif-condensed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:minLines="2"
- android:maxLines="2"
- android:paddingTop="4dip" />
+ android:minLines="1"
+ android:maxLines="1"
+ android:ellipsize="marquee" />
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/layout/resolver_different_item_header.xml b/core/res/res/layout/resolver_different_item_header.xml
new file mode 100644
index 0000000..5889136
--- /dev/null
+++ b/core/res/res/layout/resolver_different_item_header.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2014, 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.
+ */
+-->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alwaysShow="true"
+ android:text="@string/use_a_different_app"
+ android:minHeight="56dp"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="start|center_vertical"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:background="@color/white"
+ android:elevation="8dp"
+ />
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index 8e57543..727f9c6 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -21,38 +21,36 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="260dp"
+ android:maxCollapsedHeight="192dp"
android:maxCollapsedHeightSmall="56dp"
android:id="@id/contentPanel"
>
<TextView android:id="@+id/title"
android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_height="wrap_content"
android:layout_alwaysShow="true"
+ android:minHeight="56dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="start|center_vertical"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
android:background="@color/white"
android:elevation="8dp"
/>
- <GridView
+ <ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/resolver_list"
- android:numColumns="4"
- android:columnWidth="128dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:divider="@null"
/>
<TextView android:id="@+id/empty"
@@ -72,14 +70,15 @@
android:layout_height="wrap_content"
android:layout_ignoreOffset="true"
android:layout_alwaysShow="true"
- android:gravity="end"
+ android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
android:background="@color/white"
- android:paddingBottom="16dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
android:elevation="8dp">
<Button android:id="@+id/button_once"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index 0bd0e14..884f41e 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -21,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="48dp"
+ android:maxCollapsedHeight="144dp"
android:id="@id/contentPanel"
>
@@ -35,26 +35,28 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="80dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:layout_height="64dp"
android:orientation="horizontal"
>
+ <ImageView android:id="@+id/icon"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="start|top"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginTop="20dp"
+ android:scaleType="fitCenter"
+ />
<TextView android:id="@+id/title"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginStart="16dp"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="start|center_vertical"
android:paddingEnd="16dp"
/>
- <ImageView android:id="@+id/icon"
- android:layout_width="56dp"
- android:layout_height="56dp"
- android:layout_gravity="center_vertical"
- android:scaleType="fitCenter"
- />
</LinearLayout>
<LinearLayout
@@ -64,13 +66,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
- android:gravity="end"
+ android:gravity="end|center_vertical"
android:orientation="horizontal"
android:layoutDirection="locale"
android:measureWithLargestChild="true"
- android:paddingBottom="16dp"
- android:paddingStart="32dp"
- android:paddingEnd="32dp"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="12dp"
+ android:paddingEnd="12dp"
android:background="@color/white"
android:elevation="8dp">
<Button android:id="@+id/button_once"
@@ -99,21 +102,16 @@
android:background="?android:attr/dividerVertical" />
</LinearLayout>
- <GridView
+ <ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/resolver_list"
- android:numColumns="4"
- android:columnWidth="128dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:paddingTop="16dp"
- android:paddingBottom="16dp"
android:background="@color/white"
android:elevation="8dp"
android:nestedScrollingEnabled="true"
+ android:divider="@null"
/>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 483eb6d..08d2211 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -18,20 +18,17 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:focusable="true" >
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<include
- layout="@layout/time_header_label"
- android:layout_width="match_parent"
- android:layout_height="@dimen/timepicker_header_height"
- android:layout_gravity="center" />
+ layout="@layout/time_header_label"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/timepicker_header_height"
+ android:layout_gravity="center" />
<android.widget.RadialTimePickerView
- android:id="@+id/radial_picker"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/timepicker_radial_picker_dimen"
- android:layout_gravity="center"
- android:focusable="true"
- android:focusableInTouchMode="true" />
+ android:id="@+id/radial_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/timepicker_radial_picker_dimen"
+ android:layout_gravity="center" />
</LinearLayout>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b6c876d..35ff766 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1228,9 +1228,9 @@
<string name="smv_application" msgid="3307209192155442829">"Aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila své vlastní vynucené zásady StrictMode."</string>
<string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil své vlastní vynucené zásady StrictMode."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android se upgraduje..."</string>
- <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizace aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+ <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimalizování aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"Spouštění aplikací."</string>
- <string name="android_upgrading_complete" msgid="1405954754112999229">"Probíhá dokončování spouštění."</string>
+ <string name="android_upgrading_complete" msgid="1405954754112999229">"Dokončování inicializace."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"Běží aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Dotykem přepnete aplikaci"</string>
<string name="heavy_weight_switcher_title" msgid="7153167085403298169">"Přepnout aplikace?"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 451ac5d..fb635dd 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1294,7 +1294,7 @@
<string name="sms_control_yes" msgid="3663725993855816807">"Autoriser"</string>
<string name="sms_control_no" msgid="625438561395534982">"Refuser"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> souhaite envoyer un message à <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"Ce "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"Ceci "<b>"peut entraîner des frais"</b>" sur votre compte."</string>
<string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Cela entraînera des frais sur votre compte."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Envoyer"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Annuler"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 88adba5..7add9a6 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1294,8 +1294,8 @@
<string name="sms_control_yes" msgid="3663725993855816807">"Izinkan"</string>
<string name="sms_control_no" msgid="625438561395534982">"Tolak"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ingin mengirim pesan kepada <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" terhadap akun seluler Anda."</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan terhadap akun seluler Anda."</b></string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"Tindakan ini "<b>"dapat menimbulkan tagihan"</b>" untuk ponsel Anda."</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Tindakan ini akan menimbulkan tagihan untuk ponsel Anda."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Kirim"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Batal"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Ingat pilihan saya"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 3120104..7a72fd3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1588,7 +1588,7 @@
<string name="media_route_status_in_use" msgid="4533786031090198063">"בשימוש"</string>
<string name="display_manager_built_in_display_name" msgid="2583134294292563941">"מסך מובנה"</string>
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"מסך HDMI"</string>
- <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string>
+ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת-על #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", מאובטח"</string>
<string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"העברת מסך מתבצעת"</string>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 5259152..06b6efe 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -25,4 +25,6 @@
<item>302720</item>
<item>302780</item>
</string-array>
+
+ <integer name="config_mobile_mtu">1410</integer>
</resources>
diff --git a/core/res/res/values-mcc310-mnc004/config.xml b/core/res/res/values-mcc310-mnc004/config.xml
index 2778b6e..423e250 100644
--- a/core/res/res/values-mcc310-mnc004/config.xml
+++ b/core/res/res/values-mcc310-mnc004/config.xml
@@ -34,11 +34,4 @@
</string-array>
<bool name="config_auto_attach_data_on_creation">false</bool>
-
- <!-- Values for GPS configuration (Verizon) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>LPP_PROFILE=3</item>
- <item>GPS_LOCK=3</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 3b95db5..62001d9 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -25,10 +25,4 @@
-->
<integer name="config_mobile_mtu">1422</integer>
- <!-- Values for GPS configuration (Sprint) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index 00d2db8..f1936f4 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,10 +33,4 @@
<item>315</item>
<item>316</item>
</string-array>
- <!-- Values for GPS configuration (AT&T) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x33</item>
- <item>LPP_PROFILE=3</item>
- <item>GPS_LOCK=1</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 2f9394a..28cd695 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,10 +25,8 @@
-->
<integer name="config_mobile_mtu">1440</integer>
- <!-- Values for GPS configuration (T-Mobile) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITEIS=0x33</item>
- <item>GPS_LOCK=1</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
+ <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+ carrier provisioning. If false: hard disabled. If true: then depends on carrier
+ provisioning, availability etc -->
+ <bool name="config_carrier_volte_vt_available">true</bool>
</resources>
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 8069d13..b863aae 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -40,10 +40,9 @@
<item>315</item>
<item>316</item>
</string-array>
- <!-- Values for GPS configuration (AT&T) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x33</item>
- <item>GPS_LOCK=1</item>
- <item>LPP_PROFILE=3</item>
+ <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+ <string-array name="config_twoDigitNumberPattern">
+ <item>"0"</item>
+ <item>"00"</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc311-mnc190/config.xml b/core/res/res/values-mcc311-mnc190/config.xml
index b4e436d..a6c4d1b 100644
--- a/core/res/res/values-mcc311-mnc190/config.xml
+++ b/core/res/res/values-mcc311-mnc190/config.xml
@@ -37,11 +37,4 @@
note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
<string translatable="false" name="config_tether_apndata">Tether,broadband.cellular1.net,,,,,,,,,311,190,,DUN</string>
- <!-- Values for GPS configuration (Sprint) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=2</item>
- </string-array>
-
</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index cd5d55b..cf19235 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -38,17 +38,10 @@
be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
<bool name="imsServiceAllowTurnOff">false</bool>
- <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+ <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
carrier provisioning. If false: hard disabled. If true: then depends on carrier
provisioning, availability etc -->
- <bool name="config_mobile_allow_volte_vt">false</bool>
+ <bool name="config_carrier_volte_vt_available">false</bool>
<bool name="config_auto_attach_data_on_creation">false</bool>
-
- <!-- Values for GPS configuration (Verizon) -->
- <string-array translatable="false" name="config_gpsParameters">
- <item>CAPABILITIES=0x31</item>
- <item>GPS_LOCK=3</item>
- <item>LPP_PROFILE=3</item>
- </string-array>
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 0a109ba..2e0792a 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1774,6 +1774,6 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Pedir PIN antes de liberar"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Pedir padrão de desbloqueio antes de liberar"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Pedir senha antes de liberar"</string>
- <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros, que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
+ <string name="battery_saver_description" msgid="2510530476513605742">"Para ajudar a melhorar a vida útil da bateria, a economia de bateria reduz o desempenho do dispositivo e restringe a vibração e a maioria dos dados em segundo plano. É possível que apps de e-mail, mensagens, entre outros que dependem de sincronização não sejam atualizados a menos que sejam abertos.\n\nA economia de bateria é desativada automaticamente quando o dispositivo estiver carregando."</string>
<string name="downtime_condition_summary" msgid="8761776337475705749">"Até o período de inatividade terminar às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index daad675..f95d29d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1295,7 +1295,7 @@
<string name="sms_control_no" msgid="625438561395534982">"Kataza"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ingependa kutuma ujumbe kwa <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>."</string>
<string name="sms_short_code_details" msgid="5873295990846059400">"Hii "<b>"huenda ikasababisha ulipe gharama"</b>" kwenye akaunti ya kifaa chako cha mkononi."</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itasababisha ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"Hii itafanya ulipe gharama kwenye akaunti ya kifaa chako cha mkononi."</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"Tuma"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"Ghairi"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"Kumbuka chaguo yangu"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 516bea4..2c0ed15 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -54,17 +54,17 @@
<string name="serviceErased" msgid="1288584695297200972">"அழித்தல் வெற்றியடைந்தது."</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"தவறான கடவுச்சொல்."</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI நிறைவடைந்தது."</string>
- <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய PIN தவறானது."</string>
+ <string name="badPin" msgid="9015277645546710014">"உள்ளிட்ட பழைய பின் தவறானது."</string>
<string name="badPuk" msgid="5487257647081132201">"உள்ளிட்ட PUK2 தவறானது."</string>
<string name="mismatchPin" msgid="609379054496863419">"உள்ளிட்ட PINகள் பொருந்தவில்லை."</string>
- <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐத் தட்டச்சு செய்யவும்."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின் ஐத் தட்டச்சு செய்யவும்."</string>
<string name="invalidPuk" msgid="8761456210898036513">"8 அல்லது அதற்கு மேல் எண்கள் உள்ள PUK ஐத் தட்டச்சு செய்யவும்."</string>
- <string name="needPuk" msgid="919668385956251611">"உங்கள் SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
- <string name="needPuk2" msgid="4526033371987193070">"SIM கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
- <string name="enablePin" msgid="209412020907207950">"தோல்வி, SIM/RUIM பூட்டை இயக்கவும்."</string>
+ <string name="needPuk" msgid="919668385956251611">"உங்கள் சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது. அதைத் திறக்க PUK குறியீட்டைத் உள்ளிடவும்."</string>
+ <string name="needPuk2" msgid="4526033371987193070">"சிம் கார்டைத் தடுப்பு நீக்க PUK2 ஐ உள்ளிடவும்."</string>
+ <string name="enablePin" msgid="209412020907207950">"தோல்வி, சிம்/RUIM பூட்டை இயக்கவும்."</string>
<plurals name="pinpuk_attempts">
- <item quantity="one" msgid="6596245285809790142">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
- <item quantity="other" msgid="7530597808358774740">"SIM பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="one" msgid="6596245285809790142">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="other" msgid="7530597808358774740">"சிம் பூட்டப்படுவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -76,7 +76,7 @@
<string name="CwMmi" msgid="9129678056795016867">"அழைப்பு காத்திருப்பு"</string>
<string name="BaMmi" msgid="455193067926770581">"அழைப்புத் தவிர்ப்பு"</string>
<string name="PwdMmi" msgid="7043715687905254199">"கடவுச்சொல்லை மாற்று"</string>
- <string name="PinMmi" msgid="3113117780361190304">"PIN ஐ மாற்று"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"பின்னை மாற்று"</string>
<string name="CnipMmi" msgid="3110534680557857162">"இருக்கும் எண்ணை அழைக்கிறது"</string>
<string name="CnirMmi" msgid="3062102121430548731">"அழைப்பு எண் வரையறுக்கப்பட்டது"</string>
<string name="ThreeWCMmi" msgid="9051047170321190368">"மும்முனை அழைப்பு"</string>
@@ -289,11 +289,11 @@
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"நிகழ்வுகளுக்குச் செய்தி வழியாகப் பதிலை அனுப்புதல்"</string>
<string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"உள்வரும் அழைப்புகளுக்கான நிகழ்வுகளுக்கு, செய்தி வழியாகப் பதிலளிப்பதை நிர்வகிப்பதற்கு, பிற மெசேஜ் பயன்பாடுகளுக்குக் கோரிக்கைகளை அனுப்புவதற்குப் பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_readSms" msgid="8745086572213270480">"உங்கள் உரைச் செய்திகளை (SMS அல்லது MMS) படித்தல்"</string>
- <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
- <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+ <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"உங்கள் டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
+ <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"உங்கள் மொபைல் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS குறுஞ்செய்திகளைப் படிக்கப் பயன்பாட்டை அனுமதிக்கிறது. SMS குறுஞ்செய்திகளின் உள்ளடக்கம் அல்லது ரகசியத்தன்மை ஆகியவற்றைப் பொருட்படுத்தாமல் அச்செய்திகளைப் படிக்க பயன்பாட்டை இது அனுமதிக்கிறது."</string>
<string name="permlab_writeSms" msgid="3216950472636214774">"உங்கள் உரைச் செய்திகளைத் (SMS அல்லது MMS) திருத்துதல்"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
- <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது SIM கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"டேப்லெட் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
+ <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ஃபோன் அல்லது சிம் கார்டில் சேமிக்கப்பட்ட SMS செய்திகளை எழுத, பயன்பாட்டை அனுமதிக்கிறது. தீங்குவிளைவிக்கும் பயன்பாடுகள் செய்திகளை நீக்கலாம்."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"உரைச் செய்திகளைப் (WAP) பெறுதல்"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP செய்திகளைப் பெற, செயற்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது. உங்களுக்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்க அல்லது நீக்குவதற்கான திறன் இந்த அனுமதியில் உள்ளடங்கும்."</string>
<string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth செய்திகளைப் (MAP) பெறுதல்"</string>
@@ -541,8 +541,8 @@
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ஆடியோவைப் பதிவுசெய்தல்"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"மைக்ரோஃபோன் மூலம் ஆடியோவைப் பதிவுசெய்ய பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இல்லாமல் எந்நேரத்திலும் ஆடியோவைப் பதிவுசெய்ய இந்த அனுமதி பயன்பாட்டை அனுமதிக்கிறது."</string>
- <string name="permlab_sim_communication" msgid="1180265879464893029">"SIM தகவல்தொடர்பு"</string>
- <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
+ <string name="permlab_sim_communication" msgid="1180265879464893029">"சிம் தகவல்தொடர்பு"</string>
+ <string name="permdesc_sim_communication" msgid="5725159654279639498">"சிம் க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
<string name="permlab_camera" msgid="3616391919559751192">"படங்கள் மற்றும் வீடியோக்களை எடுத்தல்"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"கேமரா மூலமாகப் படங்களையும், வீடியோக்களையும் எடுக்க பயன்பாட்டை அனுமதிக்கிறது. உங்கள் உறுதிப்படுத்தல் இன்றி கேமராவை எந்நேரத்திலும் பயன்படுத்தப் பயன்பாட்டை இது அனுமதிக்கிறது."</string>
<string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"கேமரா பயன்பாட்டில் இருக்கும்போது டிரான்ஸ்மிட் இன்டிகேட்டர் LED ஐ முடக்குதல்"</string>
@@ -882,14 +882,14 @@
<string name="sipAddressTypeWork" msgid="6920725730797099047">"அலுவலகம்"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"மற்றவை"</string>
<string name="quick_contacts_not_available" msgid="746098007828579688">"இதைப் பார்ப்பதற்குகந்த பயன்பாடு எதுவும் நிறுவப்படவில்லை."</string>
- <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய PIN குறியீட்டை உள்ளிடவும்"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK மற்றும் புதிய பின் குறியீட்டை உள்ளிடவும்"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK குறியீடு"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய PIN குறியீடு"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"புதிய பின் குறியீடு"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, PIN ஐ உள்ளிடவும்"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான PIN குறியீடு."</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, பின்னை உள்ளிடவும்"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான பின் குறியீடு."</string>
<string name="keyguard_label_text" msgid="861796461028298424">"தடைநீக்க, மெனுவை அழுத்தி பின்பு 0 ஐ அழுத்தவும்."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"அவசர எண்"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"சேவை இல்லை."</string>
@@ -907,13 +907,13 @@
<string name="lockscreen_charged" msgid="321635745684060624">"சார்ஜ் செய்யப்பட்டது"</string>
<string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"உங்கள் சார்ஜரை இணைக்கவும்."</string>
- <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"SIM கார்டு இல்லை"</string>
- <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் SIM கார்டு இல்லை."</string>
- <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் SIM கார்டு இல்லை."</string>
- <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"SIM கார்டைச் செருகவும்."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. SIM கார்டைச் செருகவும்."</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத SIM கார்டு."</string>
- <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் SIM கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு SIM கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
+ <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"சிம் கார்டு இல்லை"</string>
+ <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+ <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"தொலைபேசியில் சிம் கார்டு இல்லை."</string>
+ <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"சிம் கார்டைச் செருகவும்."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"சிம் கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. சிம் கார்டைச் செருகவும்."</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"பயன்படுத்த முடியாத சிம் கார்டு."</string>
+ <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"உங்கள் சிம் கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு சிம் கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
<string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"முந்தைய ட்ராக்"</string>
<string name="lockscreen_transport_next_description" msgid="573285210424377338">"அடுத்த ட்ராக்"</string>
<string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"இடைநிறுத்து"</string>
@@ -923,13 +923,13 @@
<string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"வேகமாக முன்செல்"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"அவசர அழைப்புகள் மட்டும்"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"நெட்வொர்க் பூட்டப்பட்டது"</string>
- <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"சிம் கார்டு PUK பூட்டுதல் செய்யப்பட்டுள்ளது."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"பயனர் கையேட்டைப் பார்க்கவும் அல்லது வாடிக்கையாளர் சேவையைத் தொடர்புகொள்ளவும்."</string>
- <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM கார்டு பூட்டப்பட்டுள்ளது."</string>
- <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM கார்டைத் திறக்கிறது..."</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
+ <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"சிம் கார்டைத் திறக்கிறது..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
- <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+ <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி டேப்லெட்டைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> முறை தவறாக வரைந்தால், உங்கள் Google உள்நுழைவைப் பயன்படுத்தி மொபைலைத் திறக்குமாறு கேட்கப்படுவீர்கள். \n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"டேப்லெட்டைத் தடைநீக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்ப இயல்புநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவும் இழக்கப்படும்."</string>
@@ -1284,8 +1284,8 @@
<string name="wifi_p2p_invitation_to_connect_title" msgid="4958803948658533637">"இணைவதற்கான அழைப்பு"</string>
<string name="wifi_p2p_from_message" msgid="570389174731951769">"அனுப்புநர்:"</string>
<string name="wifi_p2p_to_message" msgid="248968974522044099">"பெறுநர்:"</string>
- <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான PIN ஐ உள்ளிடவும்:"</string>
- <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"PIN:"</string>
+ <string name="wifi_p2p_enter_pin_message" msgid="5920929550367828970">"பின்வரும் அவசியமான பின்னை உள்ளிடவும்:"</string>
+ <string name="wifi_p2p_show_pin_message" msgid="8530563323880921094">"பின்:"</string>
<string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="8012981257742232475">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் டேப்லெட் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
<string name="wifi_p2p_frequency_conflict_message" product="default" msgid="7363907213787469151">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> உடன் மொபைல் இணைக்கப்படும்போது, வைஃபையிலிருந்து தற்காலிகமாகத் துண்டிக்கப்படும்."</string>
<string name="select_character" msgid="3365550120617701745">"எழுத்துக்குறியைச் செருகு"</string>
@@ -1302,10 +1302,10 @@
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"அமைப்பு > பயன்பாடுகள் என்பதில் பிறகு நீங்கள் மாற்றலாம்"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"எப்போதும் அனுமதி"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ஒருபோதும் அனுமதிக்காதே"</string>
- <string name="sim_removed_title" msgid="6227712319223226185">"SIM கார்டு அகற்றப்பட்டது"</string>
- <string name="sim_removed_message" msgid="5450336489923274918">"சரியான SIM கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"சிம் கார்டு அகற்றப்பட்டது"</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"சரியான சிம் கார்டைச் செருகி, மறுதொடக்கம் செய்யும் வரை செல்லுலார் நெட்வொர்க் கிடைக்காது."</string>
<string name="sim_done_button" msgid="827949989369963775">"முடிந்தது"</string>
- <string name="sim_added_title" msgid="3719670512889674693">"SIM கார்டு சேர்க்கப்பட்டது"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"சிம் கார்டு சேர்க்கப்பட்டது"</string>
<string name="sim_added_message" msgid="7797975656153714319">"செல்லுலார் நெட்வொர்க்கை அணுக உங்கள் சாதனத்தை மறுதொடக்கம் செய்யவும்."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"மறுதொடக்கம்"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"நேரத்தை அமை"</string>
@@ -1568,7 +1568,7 @@
<string name="activity_resolver_use_once" msgid="2404644797149173758">"இப்போது மட்டும்"</string>
<string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s பணி சுயவிவரத்தை ஆதரிக்காது"</string>
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"டேப்லெட்"</string>
- <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"மொபைல்"</string>
+ <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ஃபோன்"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string>
<string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string>
<string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
@@ -1600,21 +1600,21 @@
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"வடிவத்தை மறந்துவிட்டீர்களா"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"தவறான வடிவம்"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"தவறான கடவுச்சொல்"</string>
- <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான PIN"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான பின்"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"உங்கள் வடிவத்தை வரையவும்"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ஐ உள்ளிடவும்"</string>
- <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ஐ உள்ளிடுக"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"சிம் பின்னை உள்ளிடவும்"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"பின்னை உள்ளிடுக"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
- <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய PIN குறியீட்டை உறுதிப்படுத்தவும்"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
- <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான PIN குறியீடு."</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐ உள்ளிடவும்."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
+ <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"தவறான பின் குறியீடு."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின்னை உள்ளிடவும்."</string>
<string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK குறியீட்டில் 8 எழுத்துக்குறிகள் இருக்க வேண்டும்."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் SIM ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN குறியீடுகள் பொருந்தவில்லை"</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம் ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"அதிகமான வடிவ முயற்சிகள்"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"திறக்க, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"பயனர்பெயர் (மின்னஞ்சல்)"</string>
@@ -1623,7 +1623,7 @@
<string name="kg_login_invalid_input" msgid="5754664119319872197">"தவறான பயனர்பெயர் அல்லது கடவுச்சொல்."</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"உங்கள் பயனர்பெயர் அல்லது கடவுச்சொல்லை மறந்துவிட்டீர்களா?\n"<b>"google.com/accounts/recovery"</b>" ஐப் பார்வையிடவும்."</string>
<string name="kg_login_checking_password" msgid="1052685197710252395">"கணக்கைச் சரிபார்க்கிறது…"</string>
- <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்பநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவையும் இழப்பீர்கள்."</string>
@@ -1734,15 +1734,15 @@
<string name="reason_service_unavailable" msgid="7824008732243903268">"பிரிண்டர் இயக்கத்தில் இல்லை"</string>
<string name="print_service_installed_title" msgid="2246317169444081628">"<xliff:g id="NAME">%s</xliff:g> சேவை நிறுவப்பட்டது"</string>
<string name="print_service_installed_message" msgid="5897362931070459152">"இயக்குவதற்குத் தட்டவும்"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி PIN ஐ உள்ளிடவும்"</string>
- <string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN ஐ உள்ளிடவும்"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"நிர்வாகி பின்னை உள்ளிடவும்"</string>
+ <string name="restr_pin_enter_pin" msgid="3395953421368476103">"பின்னை உள்ளிடவும்"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"தவறானது"</string>
- <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு PIN"</string>
- <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய PIN"</string>
- <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய PIN ஐ உறுதிப்படுத்தவும்"</string>
- <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு PIN ஐ உருவாக்கவும்"</string>
+ <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"நடப்பு பின்"</string>
+ <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"புதிய பின்"</string>
+ <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"புதிய பின்னை உறுதிப்படுத்தவும்"</string>
+ <string name="restr_pin_create_pin" msgid="8017600000263450337">"வரம்புகளைத் திருத்துவதற்கு பின்னை உருவாக்கவும்"</string>
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PINகள் பொருந்தவில்லை. மீண்டும் முயற்சிக்கவும்."</string>
- <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
+ <string name="restr_pin_error_too_short" msgid="8173982756265777792">"பின் மிகவும் சிறியதாக உள்ளது. குறைந்தது 4 இலக்கங்கள் இருக்க வேண்டும்."</string>
<plurals name="restr_pin_countdown">
<item quantity="one" msgid="311050995198548675">"1 வினாடி கழித்து முயற்சிக்கவும்"</item>
<item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்"</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index c4a6e53c..cd0ef0b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1294,8 +1294,8 @@
<string name="sms_control_yes" msgid="3663725993855816807">"允許"</string>
<string name="sms_control_no" msgid="625438561395534982">"拒絕"</string>
<string name="sms_short_code_confirm_message" msgid="1645436466285310855">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> 要求將訊息傳送至 <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>。"</string>
- <string name="sms_short_code_details" msgid="5873295990846059400">"這"<b>"可能會將收費計入"</b>"您的流動服務帳戶中。"</string>
- <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"這會將收費計入您的流動服務帳戶中。"</b></string>
+ <string name="sms_short_code_details" msgid="5873295990846059400">"您的流動服務帳戶"<b>"可能因此繳付費用"</b>"。"</string>
+ <string name="sms_premium_short_code_details" msgid="7869234868023975"><b>"您的流動服務帳戶將因此繳付費用。"</b></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"發送"</string>
<string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"取消"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"記住我的選擇"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 093ce63..fdb54ec 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -376,7 +376,7 @@
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"允許應用程式啟動完整備份確認使用者介面 (不建議任何應用程式使用)。"</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"顯示未授權視窗"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"允許應用程式為內部系統使用者介面建立視窗 (不建議一般應用程式使用)。"</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示内容"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"在其他應用程式之上顯示內容"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"允許應用程式在其他應用程式頂層或使用者介面的特定部分繪圖。這可能會干擾您在所有應用程式中的介面使用行為,或是使您在其他應用程式中預期看到的內容發生變化。"</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"編輯全域動畫速度"</string>
<string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允許應用程式隨時變更全域的動畫速度 (更快或更慢)。"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3628355..a00ed5d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1949,6 +1949,8 @@
<attr name="listItemLayout" format="reference" />
<attr name="progressLayout" format="reference" />
<attr name="horizontalProgressLayout" format="reference" />
+ <!-- @hide Whether fullDark, etc. should use default values if null. -->
+ <attr name="needsDefaultBackgrounds" format="boolean" />
</declare-styleable>
<!-- Fragment animation class attributes. -->
@@ -4339,12 +4341,14 @@
<attr name="minDate" format="string" />
<!-- The maximal date shown by this calendar view in mm/dd/yyyy format. -->
<attr name="maxDate" format="string" />
+ <!-- The first day of week according to {@link java.util.Calendar}. -->
+ <attr name="firstDayOfWeek" />
<!-- @hide The layout of the date picker. -->
<attr name="internalLayout" format="reference" />
<!-- @hide The layout of the legacy DatePicker. -->
<attr name="legacyLayout" />
<!-- The background color for the date selector 's day of week. -->
- <attr name="dayOfWeekBackgroundColor" format="color" />
+ <attr name="dayOfWeekBackground" format="color|reference" />
<!-- The text color for the date selector's day of week. -->
<attr name="dayOfWeekTextAppearance" format="reference" />
<!-- The month's text appearance in the date selector. -->
@@ -4353,8 +4357,8 @@
<attr name="headerDayOfMonthTextAppearance" format="reference" />
<!-- The year's text appearance in the date selector. -->
<attr name="headerYearTextAppearance" format="reference" />
- <!-- The background color for the date selector. -->
- <attr name="headerBackgroundColor" />
+ <!-- The background for the date selector. -->
+ <attr name="headerBackground" />
<!-- @hide The selected text color for the date selector. Used as a
backup if the text appearance does not explicitly have a color
set for the selected state. -->
@@ -4479,12 +4483,12 @@
<!-- The row boundary delimiting the top of the group of cells
occupied by this view. -->
<attr name="layout_row" format="integer" />
- <!-- The row span: the difference between the bottom and top
+ <!-- The row span: the difference between the top and bottom
boundaries delimiting the group of cells occupied by this view.
The default is one.
See {@link android.widget.GridLayout.Spec}. -->
<attr name="layout_rowSpan" format="integer" min="1" />
- <!-- The relative proportion of horizontal space that should be allocated to this view
+ <!-- The relative proportion of vertical space that should be allocated to this view
during excess space distribution. -->
<attr name="layout_rowWeight" format="float" />
<!-- The column boundary delimiting the left of the group of cells
@@ -4495,7 +4499,7 @@
The default is one.
See {@link android.widget.GridLayout.Spec}. -->
<attr name="layout_columnSpan" format="integer" min="1" />
- <!-- The relative proportion of vertical space that should be allocated to this view
+ <!-- The relative proportion of horizontal space that should be allocated to this view
during excess space distribution. -->
<attr name="layout_columnWeight" format="float" />
<!-- Gravity specifies how a component should be placed in its group of cells.
@@ -4651,29 +4655,29 @@
<attr name="legacyLayout" format="reference" />
<!-- @hide The layout of the time picker. -->
<attr name="internalLayout" />
- <!-- The text appearance for the AM/PM header of the TimePicker. -->
+ <!-- The text appearance for the AM/PM header. -->
<attr name="headerAmPmTextAppearance" format="reference" />
- <!-- The text appearance for the time header of the TimePicker. -->
+ <!-- The text appearance for the time header. -->
<attr name="headerTimeTextAppearance" format="reference" />
<!-- @hide The text color for selected time header of the TimePicker.
This will override the value from the text appearance if it does
not explicitly have a color set for the selected state. -->
<attr name="headerSelectedTextColor" format="color" />
- <!-- The background color for the header of the TimePicker. -->
- <attr name="headerBackgroundColor" format="color" />
- <!-- The color for the hours/minutes numbers of the TimePicker. -->
+ <!-- The background for the header containing the currently selected time. -->
+ <attr name="headerBackground" />
+ <!-- The color for the hours/minutes numbers. -->
<attr name="numbersTextColor" format="color" />
- <!-- The background color for the hours/minutes numbers of the TimePicker. -->
+ <!-- The background color for the hours/minutes numbers. -->
<attr name="numbersBackgroundColor" format="color" />
- <!-- The color for the AM/PM selectors of the TimePicker. -->
+ <!-- The color for the AM/PM selectors. -->
<attr name="amPmTextColor" format="color" />
- <!-- The background color state list for the AM/PM selectors of the TimePicker. -->
+ <!-- The background color state list for the AM/PM selectors. -->
<attr name="amPmBackgroundColor" format="color" />
<!-- @hide The background color for the AM/PM selectors of the
TimePicker when selected. Used if the background color does not
explicitly have a color set for the selected state. -->
<attr name="amPmSelectedBackgroundColor" format="color" />
- <!-- The color for the hours/minutes selector of the TimePicker. -->
+ <!-- The color for the hours/minutes selector. -->
<attr name="numbersSelectorColor" format="color" />
<!-- Defines the look of the widget. Prior to the L release, the only choice was
spinner. As of L, with the Material theme selected, the default layout is clock,
@@ -5684,12 +5688,12 @@
<attr name="maximumAngle" format="float" />
</declare-styleable>
- <!-- Use <code>patternMotion</code> as the root tag of the XML resource that
- describes a {@link android.transition.PatternMotion}. This must be used
+ <!-- Use <code>patternPathMotion</code> as the root tag of the XML resource that
+ describes a {@link android.transition.PatternPathMotion}. This must be used
within a transition with which the PathMotion should be associated. -->
- <declare-styleable name="PatternMotion">
- <!-- The path string describing the pattern to use for the PathMotion. -->
- <attr name="pathData" />
+ <declare-styleable name="PatternPathMotion">
+ <!-- The path string describing the pattern to use for the PathPathMotion. -->
+ <attr name="patternPathData" format="string" />
</declare-styleable>
<!-- ========================== -->
@@ -6598,12 +6602,12 @@
<flag name="vertical" value="0x2" />
</attr>
<!-- Optional parameter which indicates where this widget can be shown,
- ie. home screen, keyguard, recents or any combination thereof.
+ ie. home screen, keyguard, search bar or any combination thereof.
Supports combined values using | operator. -->
<attr name="widgetCategory" format="integer">
<flag name="home_screen" value="0x1" />
<flag name="keyguard" value="0x2" />
- <flag name="recents" value="0x4" />
+ <flag name="searchbox" value="0x4" />
</attr>
</declare-styleable>
@@ -7115,6 +7119,8 @@
<attr name="backgroundSplit" />
<!-- Specifies a fixed height for the action mode bar. -->
<attr name="height" />
+ <!-- Specifies a layout to use for the "close" item at the starting edge. -->
+ <attr name="closeItemLayout" format="reference" />
</declare-styleable>
<declare-styleable name="SearchView">
@@ -7147,6 +7153,7 @@
<attr name="queryBackground" format="reference" />
<!-- Background for the section containing the action (e.g. voice search) -->
<attr name="submitBackground" format="reference" />
+ <attr name="focusable" />
</declare-styleable>
<declare-styleable name="Switch">
@@ -7430,6 +7437,9 @@
<!-- @removed -->
<attr name="__removed1" format="reference" />
+ <!-- TODO: Spacer to be removed from here and public.xml -->
+ <attr name="__removed2" format="reference" />
+
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
which is referenced from its
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index e905a3a..10c2518e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -939,7 +939,7 @@
{@link android.content.Intent#FLAG_ACTIVITY_MULTIPLE_TASK
Intent.FLAG_ACTIVITY_MULTIPLE_TASK}. If the value of
documentLaunchModes is <code>never</code> then any use of
-.........{@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT
+ {@link android.content.Intent#FLAG_ACTIVITY_NEW_DOCUMENT
Intent.FLAG_ACTIVITY_NEW_DOCUMENT} to launch this activity will be ignored. -->
<attr name="documentLaunchMode">
<!-- The default mode, which will create a new task only when
@@ -994,6 +994,15 @@
TaskDescription to change labels, colors and icons in the recent task list. -->
<attr name="relinquishTaskIdentity" format="boolean" />
+ <!-- Indicate that it is okay for this activity be resumed while the previous
+ activity is in the process of pausing, without waiting for the previous pause
+ to complete. Use this with caution: your activity can not acquire any exclusive
+ resources (such as opening the camera or recording audio) when it launches, or it
+ may conflict with the previous activity and fail.
+
+ <p>The default value of this attribute is <code>false</code>. -->
+ <attr name="resumeWhilePausing" format="boolean" />
+
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
describing the contents of an Android package (.apk) file. One
@@ -1678,6 +1687,7 @@
<attr name="maxRecents" />
<attr name="autoRemoveFromRecents" />
<attr name="relinquishTaskIdentity" />
+ <attr name="resumeWhilePausing" />
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index d8e14a0..939cbf1 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -19,8 +19,8 @@
<color name="background_material_dark">#ff212121</color>
<color name="background_material_light">#fffafafa</color>
- <color name="ripple_material_light">#20444444</color>
- <color name="ripple_material_dark">#20ffffff</color>
+ <color name="ripple_material_light">#40000000</color>
+ <color name="ripple_material_dark">#40ffffff</color>
<color name="button_material_dark">#ff5a595b</color>
<color name="button_material_light">#ffd6d7d7</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 988198a..ed232e2 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -351,6 +351,9 @@
point on the move. A value of 0 means no periodic scans will be used in the framework. -->
<integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>
+ <!-- Integer indicating associated scan interval in milliseconds -->
+ <integer translatable="false" name="config_wifi_framework_associated_scan_interval">10000</integer>
+
<!-- Wifi driver stop delay, in milliseconds.
Default value is 2 minutes. -->
<integer translatable="false" name="config_wifi_driver_stop_delay">120000</integer>
@@ -374,7 +377,7 @@
<bool name="config_useAttentionLight">false</bool>
<!-- If this is true, the screen will fade off. -->
- <bool name="config_animateScreenLights">true</bool>
+ <bool name="config_animateScreenLights">false</bool>
<!-- If this is true, key chords can be used to take a screenshot on the device. -->
<bool name="config_enableScreenshotChord">true</bool>
@@ -771,6 +774,9 @@
specified -->
<string name="default_wallpaper_component" translatable="false">@null</string>
+ <!-- Component name of the built in wallpaper used to display bitmap wallpapers. This must not be null. -->
+ <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.ImageWallpaper</string>
+
<!-- True if WallpaperService is enabled -->
<bool name="config_enableWallpaperService">true</bool>
@@ -1456,6 +1462,10 @@
<!-- Set to true if after a provisioning apn the radio should be restarted -->
<bool name="config_restartRadioAfterProvisioning">false</bool>
+ <!-- Boolean indicating if RADIO POWER OFF is required on receiving SIM REFRESH with RESET.
+ This will be handled by modem if it is false. -->
+ <bool name="config_requireRadioPowerOffOnSimRefreshReset">false</bool>
+
<!-- Vibrator pattern to be used as the default for notifications
that specify DEFAULT_VIBRATE.
-->
@@ -1533,6 +1543,7 @@
<item>com.android.server.notification.ValidateNotificationPeople</item>
<item>com.android.server.notification.PackagePriorityExtractor</item>
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
+ <item>com.android.server.notification.PackageVisibilityExtractor</item>
</string-array>
<!-- Flag indicating that this device does not rotate and will always remain in its default
@@ -1603,6 +1614,10 @@
<!-- default window ShowCircularMask property -->
<bool name="config_windowShowCircularMask">false</bool>
+ <!-- default value for whether circular emulators (ro.emulator.circular)
+ should show a display overlay on the screen -->
+ <bool name="config_windowEnableCircularEmulatorDisplayOverlay">false</bool>
+
<!-- Defines the default set of global actions. Actions may still be disabled or hidden based
on the current state of the device.
Each item must be one of the following strings:
@@ -1666,10 +1681,13 @@
be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
<bool name="imsServiceAllowTurnOff">true</bool>
- <!-- Flag specifying whether VoLTE & VT should be allowed on device: independent of the
+ <!-- Flag specifying whether VoLTE & VT is availasble on device -->
+ <bool name="config_device_volte_vt_available">false</bool>
+
+ <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
carrier provisioning. If false: hard disabled. If true: then depends on carrier
provisioning, availability etc -->
- <bool name="config_mobile_allow_volte_vt">true</bool>
+ <bool name="config_carrier_volte_vt_available">false</bool>
<bool name="config_networkSamplingWakesDevice">true</bool>
@@ -1690,9 +1708,13 @@
and adds page info " x/y". This config is used to set which carrier doesn't
support EMS and whether page info should be added at the beginning or the end.
We use tag 'prefix' for position beginning and 'suffix' for position end.
- Examples: <item>311480;prefix</item> <item>310260;suffix</item>
+ And use gid to distinguish different carriers which using same mcc and mnc.
+ Examples: <item>simOperatorNumber;position;gid(optional)</item>>
-->
- <string-array translatable="false" name="no_ems_support_sim_operators" />
+ <string-array translatable="false" name="no_ems_support_sim_operators">
+ <!-- VZW -->
+ <item>20404;suffix;BAE0000000000000</item>
+ </string-array>
<bool name="config_auto_attach_data_on_creation">true</bool>
@@ -1700,16 +1722,7 @@
<string-array translatable="false" name="config_gpsParameters">
<item>SUPL_HOST=supl.google.com</item>
<item>SUPL_PORT=7275</item>
- <item>XTRA_SERVER_1=http://xtrapath1.izatcloud.net/xtra2.bin</item>
- <item>XTRA_SERVER_2=http://xtrapath2.izatcloud.net/xtra2.bin</item>
- <item>XTRA_SERVER_3=http://xtrapath3.izatcloud.net/xtra2.bin</item>
<item>NTP_SERVER=north-america.pool.ntp.org</item>
<item>SUPL_VER=0x20000</item>
- <item>CAPABILITIES=0x33</item>
- <item>LPP_PROFILE=0</item>
- <item>NMEA_PROVIDER=0</item>
- <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
- <item>ERR_ESTIMATE=0</item>
- <item>INTERMEDIATE_POS=0</item>
</string-array>
</resources>
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 5f7f0ed..275a5ec 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -77,5 +77,6 @@
<!-- Default rounded corner for controls -->
<dimen name="control_corner_material">2dp</dimen>
- <dimen name="alert_dialog_padding_material">18dp</dimen>
+ <dimen name="alert_dialog_padding_material">24dp</dimen>
+ <dimen name="alert_dialog_padding_top_material">18dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 75c0e2c..5b047f7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2235,7 +2235,7 @@
<public type="attr" name="launchTaskBehindTargetAnimation" />
<public type="attr" name="launchTaskBehindSourceAnimation" />
<public type="attr" name="restrictionType" />
- <public type="attr" name="dayOfWeekBackgroundColor" />
+ <public type="attr" name="dayOfWeekBackground" />
<public type="attr" name="dayOfWeekTextAppearance" />
<public type="attr" name="headerMonthTextAppearance" />
<public type="attr" name="headerDayOfMonthTextAppearance" />
@@ -2248,7 +2248,7 @@
<public type="attr" name="timePickerDialogTheme" />
<public type="attr" name="headerTimeTextAppearance" />
<public type="attr" name="headerAmPmTextAppearance" />
- <public type="attr" name="headerBackgroundColor" />
+ <public type="attr" name="__removed2" />
<public type="attr" name="numbersTextColor" />
<public type="attr" name="numbersBackgroundColor" />
<public type="attr" name="numbersSelectorColor" />
@@ -2266,7 +2266,7 @@
<public type="attr" name="windowReenterTransition" />
<public type="attr" name="windowSharedElementReturnTransition" />
<public type="attr" name="windowSharedElementReenterTransition" />
- <public type="attr" name="__removed1" />
+ <public type="attr" name="resumeWhilePausing" />
<public type="attr" name="datePickerMode"/>
<public type="attr" name="timePickerMode"/>
<public type="attr" name="inset" />
@@ -2290,6 +2290,7 @@
<public type="attr" name="fragmentReenterTransition" />
<public type="attr" name="fragmentAllowEnterTransitionOverlap" />
<public type="attr" name="fragmentAllowReturnTransitionOverlap" />
+ <public type="attr" name="patternPathData" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f1ec5d2..5c932fd 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3443,6 +3443,9 @@
<string name="whichHomeApplication">Select a home app</string>
<!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title-->
<string name="alwaysUse">Use by default for this action.</string>
+ <!-- Title of the list of alternate options to complete an action shown when the
+ last used option is being displayed separately. -->
+ <string name="use_a_different_app">Use a different app</string>
<!-- Text displayed when the user selects the check box for setting default application. See the "Use by default for this action" check box. -->
<string name="clearDefaultHintMsg">Clear default in System settings > Apps > Downloaded.</string>
<!-- Default title for the activity chooser, when one is not given. Android allows multiple activities to perform an action. for example, there may be many ringtone pickers installed. A dialog is shown to the user allowing him to pick which activity should be used. This is the title. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4aed037..c6d0b0b 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -62,6 +62,7 @@
<item name="centerMedium">@drawable/popup_center_medium</item>
<item name="progressLayout">@layout/progress_dialog</item>
<item name="horizontalProgressLayout">@layout/alert_dialog_progress</item>
+ <item name="needsDefaultBackgrounds">false</item>
</style>
<style name="Widget.PreferenceFrameLayout">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 2a54ccf..c7d2db1 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -468,7 +468,7 @@
<item name="internalLayout">@layout/time_picker_holo</item>
<item name="headerTimeTextAppearance">@style/TextAppearance.Holo.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.TimePicker.AmPmLabel</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_holo_dark</item>
+ <item name="headerBackground">@color/timepicker_default_background_holo_dark</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_dark</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_dark</item>
@@ -484,9 +484,9 @@
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
<!-- New-style date picker attributes. -->
- <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
+ <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.DatePicker.DayOfWeekLabel</item>
- <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_dark</item>
+ <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_dark</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.YearLabel</item>
@@ -892,7 +892,7 @@
<item name="internalLayout">@layout/time_picker_holo</item>
<item name="headerTimeTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.AmPmLabel</item>
- <item name="headerBackgroundColor">@color/timepicker_default_background_holo_light</item>
+ <item name="headerBackground">@color/timepicker_default_background_holo_light</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_light</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_light</item>
@@ -908,12 +908,12 @@
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
<!-- New-style date picker attributes. -->
- <item name="dayOfWeekBackgroundColor">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
+ <item name="dayOfWeekBackground">@color/datepicker_default_header_dayofweek_background_color_holo_light</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.DayOfWeekLabel</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.YearLabel</item>
- <item name="headerBackgroundColor">@color/datepicker_default_header_selector_background_holo_light</item>
+ <item name="headerBackground">@color/datepicker_default_header_selector_background_holo_light</item>
<item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="yearListItemTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.List.YearLabel</item>
<item name="yearListSelectorColor">@color/datepicker_default_circle_background_color_holo_light</item>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 452ee11..26c7d10 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -474,6 +474,13 @@
<item name="stateListAnimator">@anim/disabled_anim_material</item>
</style>
+ <!-- Alert dialog button bar button -->
+ <style name="Widget.Material.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.Borderless.Colored">
+ <item name="minWidth">64dp</item>
+ <item name="maxLines">2</item>
+ <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
+ </style>
+
<!-- Small borderless ink button -->
<style name="Widget.Material.Button.Borderless.Small">
<item name="minHeight">48dip</item>
@@ -496,7 +503,6 @@
<style name="Widget.Material.ButtonBar.AlertDialog">
<item name="background">@null</item>
- <item name="minHeight">@dimen/alert_dialog_button_bar_height</item>
</style>
<style name="Widget.Material.SearchView">
@@ -619,7 +625,7 @@
<item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
<item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
<item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
- <item name="headerBackgroundColor">?attr/colorAccent</item>
+ <item name="headerBackground">@drawable/time_picker_header_material</item>
<item name="numbersTextColor">?attr/textColorSecondary</item>
<item name="numbersBackgroundColor">#10ffffff</item>
<item name="amPmTextColor">?attr/textColorSecondary</item>
@@ -634,13 +640,13 @@
<!-- Attributes for new-style DatePicker. -->
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
- <item name="dayOfWeekBackgroundColor">#10000000</item>
+ <item name="dayOfWeekBackground">#10000000</item>
<item name="dayOfWeekTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfWeekLabel</item>
<item name="headerMonthTextAppearance">@style/TextAppearance.Material.DatePicker.MonthLabel</item>
<item name="headerDayOfMonthTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfMonthLabel</item>
<item name="headerYearTextAppearance">@style/TextAppearance.Material.DatePicker.YearLabel</item>
<item name="headerSelectedTextColor">?attr/textColorPrimaryInverse</item>
- <item name="headerBackgroundColor">?attr/colorAccent</item>
+ <item name="headerBackground">?attr/colorAccent</item>
<item name="yearListItemTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
<item name="yearListSelectorColor">?attr/colorControlActivated</item>
<item name="calendarTextColor">?attr/textColorSecondary</item>
@@ -838,7 +844,7 @@
</style>
<style name="Widget.Material.ActionButton.CloseMode">
- <item name="background">@drawable/btn_cab_done_material</item>
+ <item name="background">?attr/selectableItemBackgroundBorderless</item>
</style>
<style name="Widget.Material.ActionButton.Overflow">
@@ -901,6 +907,7 @@
<style name="Widget.Material.ActionMode" parent="Widget.ActionMode">
<item name="titleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Material.Widget.ActionMode.Subtitle</item>
+ <item name="closeItemLayout">@layout/action_mode_close_item_material</item>
</style>
<style name="Widget.Material.FastScroll" parent="Widget.FastScroll">
@@ -935,6 +942,7 @@
<style name="Widget.Material.Light.Button.Small" parent="Widget.Material.Button.Small"/>
<style name="Widget.Material.Light.Button.Borderless" parent="Widget.Material.Button.Borderless"/>
<style name="Widget.Material.Light.Button.Borderless.Colored" parent="Widget.Material.Button.Borderless.Colored"/>
+ <style name="Widget.Material.Light.Button.ButtonBar.AlertDialog" parent="Widget.Material.Button.ButtonBar.AlertDialog" />
<style name="Widget.Material.Light.Button.Borderless.Small" parent="Widget.Material.Button.Borderless.Small"/>
<style name="Widget.Material.Light.Button.Inset" parent="Widget.Material.Button.Inset"/>
<style name="Widget.Material.Light.Button.Toggle" parent="Widget.Material.Button.Toggle" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06bd2ec..bbd891e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -283,6 +283,7 @@
<java-symbol type="bool" name="config_camera_sound_forced" />
<java-symbol type="bool" name="config_dontPreferApn" />
<java-symbol type="bool" name="config_restartRadioAfterProvisioning" />
+ <java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
<java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
<java-symbol type="bool" name="config_useFixedVolume" />
<java-symbol type="bool" name="config_forceDefaultOrientation" />
@@ -292,6 +293,7 @@
<java-symbol type="bool" name="config_windowIsRound" />
<java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="bool" name="config_windowShowCircularMask" />
+ <java-symbol type="bool" name="config_windowEnableCircularEmulatorDisplayOverlay" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
@@ -311,6 +313,7 @@
<java-symbol type="integer" name="config_shortPressOnPowerBehavior" />
<java-symbol type="integer" name="config_toastDefaultGravity" />
<java-symbol type="integer" name="config_wifi_framework_scan_interval" />
+ <java-symbol type="integer" name="config_wifi_framework_associated_scan_interval" />
<java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
<java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
<java-symbol type="integer" name="db_connection_pool_size" />
@@ -1154,6 +1157,7 @@
<java-symbol type="drawable" name="ic_corp_badge" />
<java-symbol type="drawable" name="ic_corp_icon_badge" />
<java-symbol type="drawable" name="ic_corp_icon" />
+ <java-symbol type="drawable" name="emulator_circular_window_overlay" />
<java-symbol type="drawable" name="sim_light_blue" />
<java-symbol type="drawable" name="sim_light_green" />
@@ -1633,6 +1637,7 @@
<java-symbol type="string" name="hardware" />
<java-symbol type="string" name="heavy_weight_notification" />
<java-symbol type="string" name="heavy_weight_notification_detail" />
+ <java-symbol type="string" name="image_wallpaper_component" />
<java-symbol type="string" name="input_method_binding_label" />
<java-symbol type="string" name="launch_warning_original" />
<java-symbol type="string" name="launch_warning_replace" />
@@ -1968,7 +1973,8 @@
<java-symbol type="attr" name="preferenceFragmentStyle" />
<java-symbol type="bool" name="skipHoldBeforeMerge" />
<java-symbol type="bool" name="imsServiceAllowTurnOff" />
- <java-symbol type="bool" name="config_mobile_allow_volte_vt" />
+ <java-symbol type="bool" name="config_device_volte_vt_available" />
+ <java-symbol type="bool" name="config_carrier_volte_vt_available" />
<java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
<java-symbol type="attr" name="touchscreenBlocksFocus" />
<java-symbol type="layout" name="resolver_list_with_default" />
@@ -2000,4 +2006,6 @@
<java-symbol type="id" name="parentMatrix" />
<java-symbol type="bool" name="config_auto_attach_data_on_creation" />
<java-symbol type="id" name="date_picker_month_day_year_layout" />
+ <java-symbol type="attr" name="closeItemLayout" />
+ <java-symbol type="layout" name="resolver_different_item_header" />
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 2296a12..4aca02e 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -306,7 +306,7 @@
<item name="actionOverflowMenuStyle">@style/Widget.Material.PopupMenu.Overflow</item>
<item name="actionModeBackground">@drawable/cab_background_top_material</item>
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
<item name="actionBarTabStyle">@style/Widget.Material.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Material.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Material.ActionBar.TabText</item>
@@ -333,7 +333,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Button.ButtonBar.AlertDialog</item>
<item name="segmentedButtonStyle">@style/Widget.Material.SegmentedButton</item>
<!-- SearchView attributes -->
@@ -652,7 +652,7 @@
<item name="actionOverflowMenuStyle">@style/Widget.Material.Light.PopupMenu.Overflow</item>
<item name="actionModeBackground">@drawable/cab_background_top_material</item>
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_material</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_material</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_ab_back_material</item>
<item name="actionBarTabStyle">@style/Widget.Material.Light.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Material.Light.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Material.Light.ActionBar.TabText</item>
@@ -679,7 +679,7 @@
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
<item name="buttonBarStyle">@style/Widget.Material.Light.ButtonBar</item>
- <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.Borderless.Colored</item>
+ <item name="buttonBarButtonStyle">@style/Widget.Material.Light.Button.ButtonBar.AlertDialog</item>
<item name="segmentedButtonStyle">@style/Widget.Material.Light.SegmentedButton</item>
<!-- SearchView attributes -->
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index a3c5351..77e1c530 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -54,7 +54,7 @@
protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
protected static final int SHORT_TIMEOUT = 5 * 1000; // 5 seconds
- protected static final long LONG_TIMEOUT = 50 * 1000; // 50 seconds
+ protected static final long LONG_TIMEOUT = 2 * 60 * 1000; // 2 minutes
protected static final long WIFI_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 minutes
// 2 minutes timer between wifi stop and start
protected static final long WIFI_STOP_START_INTERVAL = 2 * 60 * 1000; // 2 minutes
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
index bcf2e45..db547e2 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/downloadmanagertests/DownloadManagerTestApp.java
@@ -60,10 +60,10 @@
super.setUp();
DownloadManagerTestRunner mRunner = (DownloadManagerTestRunner)getInstrumentation();
externalDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
- assertNotNull(externalDownloadUriValue);
+ assertNotNull("download url is null", externalDownloadUriValue);
externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
- assertNotNull(externalLargeDownloadUriValue);
+ assertNotNull("large download url is null", externalLargeDownloadUriValue);
}
/**
@@ -140,7 +140,7 @@
dlRequest = mDownloadManager.enqueue(request);
waitForDownloadToStart(dlRequest);
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
// Store ID of download for later retrieval
outputFile = new DataOutputStream(fileOutput);
@@ -183,7 +183,7 @@
mContext.deleteFile(DOWNLOAD_STARTED_FLAG);
}
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
Cursor cursor = getCursor(dlRequest);
ParcelFileDescriptor pfd = null;
try {
@@ -193,7 +193,7 @@
int status = cursor.getInt(columnIndex);
int currentWaitTime = 0;
- assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000));
Log.i(LOG_TAG, "Verifying download information...");
// Verify specific info about the file (size, name, etc)...
@@ -233,7 +233,7 @@
dlRequest = mDownloadManager.enqueue(request);
// Rather large file, so wait up to 15 mins...
- assertTrue(waitForDownload(dlRequest, 15 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 15 * 60 * 1000));
Cursor cursor = getCursor(dlRequest);
ParcelFileDescriptor pfd = null;
@@ -317,7 +317,7 @@
Log.i(LOG_TAG, "Turning on WiFi...");
setWiFiStateOn(true);
Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -385,7 +385,7 @@
setWiFiStateOn(true);
Log.i(LOG_TAG, "Waiting up to 10 minutes for download to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000));
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000));
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -456,7 +456,7 @@
setAirplaneModeOn(false);
Log.i(LOG_TAG, "Waiting up to 10 minutes for donwload to complete...");
- assertTrue(waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
+ assertTrue("download not finished", waitForDownload(dlRequest, 10 * 60 * 1000)); // wait up to 10 mins
ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
verifyFileSize(pfd, filesize);
} finally {
@@ -489,11 +489,11 @@
Request request = new Request(remoteUri);
request.setTitle(filename);
dlRequest = mDownloadManager.enqueue(request);
- assertTrue(dlRequest != -1);
+ assertTrue("request id is -1 from download manager", dlRequest != -1);
downloadIds.add(dlRequest);
}
- assertTrue(waitForMultipleDownloads(downloadIds, 15 * 60 * 2000)); // wait 15 mins max
+ assertTrue("download not finished", waitForMultipleDownloads(downloadIds, 15 * 60 * 2000)); // wait 15 mins max
} finally {
removeAllCurrentDownloads();
}
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index ed8b7f7..a11e49b 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -15,7 +15,7 @@
if [[ $rebuild == true ]]; then
make -j4 FrameworksCoreInputMethodTests
- TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests.apk
+ TESTAPP=${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreInputMethodTests/FrameworksCoreInputMethodTests.apk
COMMAND="adb install -r $TESTAPP"
echo $COMMAND
$COMMAND
diff --git a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
index cc4a7c4..d4244ba 100644
--- a/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
+++ b/core/tests/inputmethodtests/src/android/os/CursorAnchorInfoTest.java
@@ -26,14 +26,12 @@
import java.util.Objects;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_NOT_FEASIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
-import static android.view.inputmethod.CursorAnchorInfo.CHARACTER_RECT_TYPE_UNSPECIFIED;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_INVISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_HAS_VISIBLE_REGION;
+import static android.view.inputmethod.CursorAnchorInfo.FLAG_IS_RTL;
public class CursorAnchorInfoTest extends InstrumentationTestCase {
- private static final RectF[] MANY_RECTS = new RectF[] {
+ private static final RectF[] MANY_BOUNDS = new RectF[] {
new RectF(101.0f, 201.0f, 301.0f, 401.0f),
new RectF(102.0f, 202.0f, 302.0f, 402.0f),
new RectF(103.0f, 203.0f, 303.0f, 403.0f),
@@ -55,25 +53,25 @@
new RectF(119.0f, 219.0f, 319.0f, 419.0f),
};
private static final int[] MANY_FLAGS_ARRAY = new int[] {
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_INVISIBLE,
- CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
- CHARACTER_RECT_TYPE_NOT_FEASIBLE,
+ FLAG_HAS_INVISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_VISIBLE_REGION | FLAG_IS_RTL,
+ FLAG_HAS_VISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION,
+ FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL,
};
@SmallTest
@@ -82,11 +80,13 @@
final int SELECTION_END = 40;
final int COMPOSING_TEXT_START = 32;
final String COMPOSING_TEXT = "test";
- final boolean INSERTION_MARKER_CLIPPED = true;
+ final int INSERTION_MARKER_FLAGS =
+ FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
final float INSERTION_MARKER_HORIZONTAL = 10.5f;
final float INSERTION_MARKER_TOP = 100.1f;
final float INSERTION_MARKER_BASELINE = 110.4f;
final float INSERTION_MARKER_BOTOM = 111.0f;
+
Matrix TRANSFORM_MATRIX = new Matrix(Matrix.IDENTITY_MATRIX);
TRANSFORM_MATRIX.setScale(10.0f, 20.0f);
@@ -94,13 +94,13 @@
builder.setSelectionRange(SELECTION_START, SELECTION_END)
.setComposingText(COMPOSING_TEXT_START, COMPOSING_TEXT)
.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM,
- INSERTION_MARKER_CLIPPED)
+ INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS)
.setMatrix(TRANSFORM_MATRIX);
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF rect = MANY_RECTS[i];
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF bounds = MANY_BOUNDS[i];
final int flags = MANY_FLAGS_ARRAY[i];
- builder.addCharacterRect(i, rect.left, rect.top, rect.right, rect.bottom, flags);
+ builder.addCharacterBounds(i, bounds.left, bounds.top, bounds.right, bounds.bottom,
+ flags);
}
final CursorAnchorInfo info = builder.build();
@@ -108,26 +108,24 @@
assertEquals(SELECTION_END, info.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info.getComposingText()));
- assertTrue(info.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info.getCharacterBounds(i));
}
- assertNull(info.getCharacterRect(-1));
- assertNull(info.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info.getCharacterBounds(-1));
+ assertNull(info.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info.getCharacterBoundsFlags(-1));
+ assertEquals(0, info.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
// Make sure that the builder can reproduce the same object.
final CursorAnchorInfo info2 = builder.build();
@@ -135,25 +133,24 @@
assertEquals(SELECTION_END, info2.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info2.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info2.getComposingText()));
- assertTrue(info2.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info2.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info2.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info2.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info2.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info2.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info2.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info2.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info2.getCharacterBounds(i));
}
- assertNull(info2.getCharacterRect(-1));
- assertNull(info2.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info2.getCharacterBounds(-1));
+ assertNull(info2.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info2.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info2.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info2.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info2.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info2.getCharacterBoundsFlags(-1));
+ assertEquals(0, info2.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
assertEquals(info, info2);
assertEquals(info.hashCode(), info2.hashCode());
@@ -163,25 +160,24 @@
assertEquals(SELECTION_END, info3.getSelectionEnd());
assertEquals(COMPOSING_TEXT_START, info3.getComposingTextStart());
assertTrue(TextUtils.equals(COMPOSING_TEXT, info3.getComposingText()));
- assertTrue(info3.isInsertionMarkerClipped());
+ assertEquals(INSERTION_MARKER_FLAGS, info3.getInsertionMarkerFlags());
assertEquals(INSERTION_MARKER_HORIZONTAL, info3.getInsertionMarkerHorizontal());
assertEquals(INSERTION_MARKER_TOP, info3.getInsertionMarkerTop());
assertEquals(INSERTION_MARKER_BASELINE, info3.getInsertionMarkerBaseline());
assertEquals(INSERTION_MARKER_BOTOM, info3.getInsertionMarkerBottom());
assertEquals(TRANSFORM_MATRIX, info3.getMatrix());
- for (int i = 0; i < MANY_RECTS.length; i++) {
- final RectF expectedRect = MANY_RECTS[i];
- assertEquals(expectedRect, info3.getCharacterRect(i));
+ for (int i = 0; i < MANY_BOUNDS.length; i++) {
+ final RectF expectedBounds = MANY_BOUNDS[i];
+ assertEquals(expectedBounds, info3.getCharacterBounds(i));
}
- assertNull(info3.getCharacterRect(-1));
- assertNull(info3.getCharacterRect(MANY_RECTS.length + 1));
+ assertNull(info3.getCharacterBounds(-1));
+ assertNull(info3.getCharacterBounds(MANY_BOUNDS.length + 1));
for (int i = 0; i < MANY_FLAGS_ARRAY.length; i++) {
final int expectedFlags = MANY_FLAGS_ARRAY[i];
- assertEquals(expectedFlags, info3.getCharacterRectFlags(i));
+ assertEquals(expectedFlags, info3.getCharacterBoundsFlags(i));
}
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED, info3.getCharacterRectFlags(-1));
- assertEquals(CHARACTER_RECT_TYPE_UNSPECIFIED,
- info3.getCharacterRectFlags(MANY_RECTS.length + 1));
+ assertEquals(0, info3.getCharacterBoundsFlags(-1));
+ assertEquals(0, info3.getCharacterBoundsFlags(MANY_BOUNDS.length + 1));
assertEquals(info.hashCode(), info3.hashCode());
builder.reset();
@@ -190,7 +186,7 @@
assertEquals(-1, uninitializedInfo.getSelectionEnd());
assertEquals(-1, uninitializedInfo.getComposingTextStart());
assertNull(uninitializedInfo.getComposingText());
- assertFalse(uninitializedInfo.isInsertionMarkerClipped());
+ assertEquals(0, uninitializedInfo.getInsertionMarkerFlags());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerHorizontal());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerTop());
assertEquals(Float.NaN, uninitializedInfo.getInsertionMarkerBaseline());
@@ -218,7 +214,7 @@
final int SELECTION_END1 = 7;
final String COMPOSING_TEXT1 = "0123456789";
final int COMPOSING_TEXT_START1 = 0;
- final boolean INSERTION_MARKER_CLIPPED1 = true;
+ final int INSERTION_MARKER_FLAGS1 = FLAG_HAS_VISIBLE_REGION;
final float INSERTION_MARKER_HORIZONTAL1 = 10.5f;
final float INSERTION_MARKER_TOP1 = 100.1f;
final float INSERTION_MARKER_BASELINE1 = 110.4f;
@@ -227,7 +223,8 @@
final int SELECTION_END2 = 8;
final String COMPOSING_TEXT2 = "9876543210";
final int COMPOSING_TEXT_START2 = 3;
- final boolean INSERTION_MARKER_CLIPPED2 = false;
+ final int INSERTION_MARKER_FLAGS2 =
+ FLAG_HAS_VISIBLE_REGION | FLAG_HAS_INVISIBLE_REGION | FLAG_IS_RTL;
final float INSERTION_MARKER_HORIZONTAL2 = 14.5f;
final float INSERTION_MARKER_TOP2 = 200.1f;
final float INSERTION_MARKER_BASELINE2 = 210.4f;
@@ -265,10 +262,10 @@
assertEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, Float.NaN, Float.NaN, Float.NaN,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
// Check Matrix.
assertEquals(
@@ -290,74 +287,74 @@
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
Float.NaN, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP2,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE2, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL2, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM2,
- INSERTION_MARKER_CLIPPED1).build());
+ INSERTION_MARKER_FLAGS1).build());
assertNotEquals(
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED1).build(),
+ INSERTION_MARKER_FLAGS1).build(),
new Builder().setMatrix(MATRIX1).setInsertionMarkerLocation(
INSERTION_MARKER_HORIZONTAL1, INSERTION_MARKER_TOP1,
INSERTION_MARKER_BASELINE1, INSERTION_MARKER_BOTOM1,
- INSERTION_MARKER_CLIPPED2).build());
+ INSERTION_MARKER_FLAGS2).build());
}
@SmallTest
@@ -394,7 +391,7 @@
final int SELECTION_END = 40;
final int COMPOSING_TEXT_START = 32;
final String COMPOSING_TEXT = "test";
- final boolean INSERTION_MARKER_CLIPPED = true;
+ final int INSERTION_MARKER_FLAGS = FLAG_HAS_VISIBLE_REGION;
final float INSERTION_MARKER_HORIZONTAL = 10.5f;
final float INSERTION_MARKER_TOP = 100.1f;
final float INSERTION_MARKER_BASELINE = 110.4f;
@@ -416,7 +413,7 @@
}
builder.setInsertionMarkerLocation(INSERTION_MARKER_HORIZONTAL, INSERTION_MARKER_TOP,
- INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_CLIPPED);
+ INSERTION_MARKER_BASELINE, INSERTION_MARKER_BOTOM, INSERTION_MARKER_FLAGS);
try {
// Coordinate transformation matrix is required if no positional information is
// specified.
@@ -438,19 +435,10 @@
}
@SmallTest
- public void testBuilderAddCharacterRect() throws Exception {
+ public void testBuilderAddCharacterBounds() throws Exception {
// A negative index should be rejected.
try {
- new Builder().addCharacterRect(-1, 0.0f, 0.0f, 0.0f, 0.0f,
- CHARACTER_RECT_TYPE_FULLY_VISIBLE);
- assertTrue(false);
- } catch (IllegalArgumentException ex) {
- }
-
- // CHARACTER_RECT_TYPE_UNSPECIFIED is not allowed.
- try {
- new Builder().addCharacterRect(0, 0.0f, 0.0f, 0.0f, 0.0f,
- CHARACTER_RECT_TYPE_UNSPECIFIED);
+ new Builder().addCharacterBounds(-1, 0.0f, 0.0f, 0.0f, 0.0f, FLAG_HAS_VISIBLE_REGION);
assertTrue(false);
} catch (IllegalArgumentException ex) {
}
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index cfc1484..f10ba96 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -405,6 +405,7 @@
# key 504 KEY_BRL_DOT8
key 580 APP_SWITCH
+key 582 VOICE_ASSIST
# Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 1e5fc4d..808f04a 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -64,7 +64,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -95,7 +95,8 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014.
+
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -114,7 +115,7 @@
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C80.2%2C19.7&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A77.5%2C22.5&chf=bg%2Cs%2C00000000&chl=GL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -131,22 +132,18 @@
<th scope="col">Distribution</th>
</tr>
<tr>
-<td>1.1 only</th>
-<td>0.1%</td>
+<td>2.0</td>
+<td>77.5%</td>
</tr>
<tr>
-<td>2.0</th>
-<td>80.2%</td>
-</tr>
-<tr>
-<td>3.0</th>
-<td>19.7%</td>
+<td>3.0</td>
+<td>22.5%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on September 9, 2014</em></p>
@@ -164,7 +161,7 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C13.6%2C10.6%2C54.2%2C20.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
+ "chart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C11.4%2C9.6%2C53.8%2C24.5&chf=bg%2Cs%2C00000000",
"data": [
{
"api": 8,
@@ -174,41 +171,38 @@
{
"api": 10,
"name": "Gingerbread",
- "perc": "13.6"
+ "perc": "11.4"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "10.6"
+ "perc": "9.6"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "26.5"
+ "perc": "25.1"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "19.8"
+ "perc": "20.7"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "7.9"
+ "perc": "8.0"
},
{
"api": 19,
"name": "KitKat",
- "perc": "20.9"
+ "perc": "24.5"
}
]
}
];
-
-
-
var SCREEN_DATA =
[
{
@@ -216,27 +210,27 @@
"Large": {
"hdpi": "0.6",
"ldpi": "0.5",
- "mdpi": "4.2",
- "tvdpi": "1.6",
- "xhdpi": "0.5"
+ "mdpi": "4.3",
+ "tvdpi": "1.7",
+ "xhdpi": "0.6"
},
"Normal": {
- "hdpi": "35.5",
- "mdpi": "11.8",
- "xhdpi": "18.4",
- "xxhdpi": "15.2"
+ "hdpi": "35.7",
+ "mdpi": "10.6",
+ "xhdpi": "19.2",
+ "xxhdpi": "16.2"
},
"Small": {
- "ldpi": "7.4"
+ "ldpi": "6.2"
},
"Xlarge": {
"hdpi": "0.3",
- "mdpi": "3.6",
+ "mdpi": "3.7",
"xhdpi": "0.4"
}
},
- "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A7.9%2C19.6%2C1.6%2C36.4%2C19.3%2C15.2&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
- "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.3%2C7.4%2C80.9%2C7.4&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c"
+ "densitychart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A6.7%2C18.6%2C1.7%2C36.6%2C20.2%2C16.2&chf=bg%2Cs%2C00000000",
+ "layoutchart": "//chart.googleapis.com/chart?chco=c4df9b%2C6fad0c&cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.4%2C7.7%2C81.7%2C6.2&chf=bg%2Cs%2C00000000"
}
];
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index d8d8c76..e5161f4 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -29,7 +29,7 @@
scaling ratio</strong> between the five primary densities (medium, high, x-high, xx-high, and
xxx-high respectively). For example, consider that the size for a launcher icon is specified to be
48x48 dp. This means the baseline (MDPI) asset is 48x48 px, and the
-high density (HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
+high-density(HDPI) asset should be 1.5x the baseline at 72x72 px, and the x-high
density (XHDPI) asset should be 2x the baseline at 96x96 px, and so on.</p>
<p class="note"><strong>Note:</strong> Android also supports low-density (LDPI) screens,
@@ -489,11 +489,12 @@
xhdpi/...
_pre_production/...
<em>working_file</em>.psd
- <em>finished_asset</em>.png</pre>
+ <em>finished_asset</em>.png
xxhdpi/...
_pre_production/...
<em>working_file</em>.psd
- <em>finished_asset</em>.png</pre>
+ <em>finished_asset</em>.png
+</pre>
<p>Because the structure in your working space is similar to that of the application, you
can quickly determine which assets should be copied to each
@@ -513,6 +514,8 @@
<em>finished_asset</em>.png
drawable-xhdpi/...
<em>finished_asset</em>.png
+ drawable-xxhdpi/...
+ <em>finished_asset</em>.png
</pre>
<p>For more information about how to save resources in the application project,
@@ -520,6 +523,21 @@
</p>
+<h3 id="xxxhdpi-launcher">Provide an xxx-high-density launcher icon</h3>
+
+<p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest density
+launcher icon image is already extra-extra-high density, the scaling process will make it appear
+less crisp. So you should provide a higher density launcher icon in the <code>drawable-xxxhdpi
+</code> directory, which the system uses instead of scaling up a smaller version of the icon.</p>
+
+<p class="note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code> qualifier is necessary only
+to provide a launcher icon that can appear larger than usual on an xxhdpi device. You do not need to
+provide xxxhdpi assets for all your app's images.</p>
+
+<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> for
+more information.</p>
+
+
<h3>Remove unnecessary metadata from final assets</h3>
<p>Although the Android SDK tools will automatically compress PNGs when packaging
diff --git a/docs/html/google/play/billing/api.jd b/docs/html/google/play/billing/api.jd
index 3d46715..bc710f9 100644
--- a/docs/html/google/play/billing/api.jd
+++ b/docs/html/google/play/billing/api.jd
@@ -1,6 +1,7 @@
-page.title=In-app Billing Version 3
+page.title=In-app Billing API
parent.title=In-app Billing
parent.link=index.html
+page.tags="billing, inapp, iap"
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/google/play/billing/billing_integrate.jd b/docs/html/google/play/billing/billing_integrate.jd
index dba43cd..052cf75 100644
--- a/docs/html/google/play/billing/billing_integrate.jd
+++ b/docs/html/google/play/billing/billing_integrate.jd
@@ -1,6 +1,7 @@
-page.title=Implementing In-app Billing <span style="font-size:16px;">(IAB Version 3)</span>
+page.title=Implementing In-app Billing
parent.title=In-app Billing
parent.link=index.html
+page.tags="inapp, billing, iap"
@jd:body
<div id="qv-wrapper">
@@ -141,15 +142,17 @@
};
</pre>
-<p>In your activity’s {@link android.app.Activity#onCreate onCreate} method, perform the binding by calling the {@link android.content.Context#bindService bindService} method. Pass the method an {@link android.content.Intent} that references the In-app Billing service and an instance of the {@link android.content.ServiceConnection} that you created.</p>
-<pre>
-@Override
-public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- bindService(new
- Intent("com.android.vending.billing.InAppBillingService.BIND"),
- mServiceConn, Context.BIND_AUTO_CREATE);
+<p>In your activity’s {@link android.app.Activity#onCreate onCreate} method, perform the binding by calling the {@link android.content.Context#bindService bindService} method. Pass the method an {@link android.content.Intent} that references the In-app Billing service and an instance of the {@link android.content.ServiceConnection} that you created, and explicitly set the Intent's target package name to <code>com.android.vending</code> — the package name of Google Play app.</p>
+
+<p class="caution"><strong>Caution:</strong> To protect the security of billing transactions, always make sure to explicitly set the intent's target package name to <code>com.android.vending</code>, using {@link android.content.Intent#setPackage(java.lang.String) setPackage()} as shown in the example below. Setting the package name explicitly ensures that <em>only</em> the Google Play app can handle billing requests from your app, preventing other apps from intercepting those requests.</p>
+
+<pre>@Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
+ serviceIntent.setPackage("com.android.vending");
+ bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
</pre>
<p>You can now use the mService reference to communicate with the Google Play service.</p>
<p class="note"><strong>Important:</strong> Remember to unbind from the In-app Billing service when you are done with your {@link android.app.Activity}. If you don’t unbind, the open service connection could cause your device’s performance to degrade. This example shows how to perform the unbind operation on a service connection to In-app Billing called {@code mServiceConn} by overriding the activity’s {@link android.app.Activity#onDestroy onDestroy} method.</p>
@@ -269,7 +272,7 @@
}
}
</pre>
-<p class="note"><strong>Security Recommendation:</strong> When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the {@code developerPayload}.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the {@code orderId}, and the {@code developerPayload} String. For added security, you should perform the checking on your own secure server. Make sure to verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} String matches the token that you sent previously with the purchase request.</p>
+<p class="note"><strong>Security Recommendation:</strong> When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the {@code developerPayload}.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the {@code orderId}, and the {@code developerPayload} String. For added security, you should perform the checking on your own secure server. Make sure to verify that the {@code orderId} is a unique value that you have not previously processed, and the {@code developerPayload} String matches the token that you sent previously with the purchase request.</p>
<h3 id="QueryPurchases">Querying for Purchased Items</h3>
<p>To retrieve information about purchases made by a user from your app, call the {@code getPurchases} method on the In-app Billing Version 3 service. Pass in to the method the In-app Billing API version (“3”), the package name of your calling app, and the purchase type (“inapp” or "subs").</p>
diff --git a/docs/html/google/play/billing/billing_reference.jd b/docs/html/google/play/billing/billing_reference.jd
index 4f5e65c..4d80964 100644
--- a/docs/html/google/play/billing/billing_reference.jd
+++ b/docs/html/google/play/billing/billing_reference.jd
@@ -1,4 +1,4 @@
-page.title=In-app Billing Reference <span style="font-size:16px;">(IAB Version 3)</span>
+page.title=In-app Billing Reference
parent.title=In-app Billing
parent.link=index.html
@jd:body
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index 3c72da1..2b78ab3 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -1,9 +1,9 @@
-page.title=Google Play In-App Subscriptions
+page.title=In-App Subscriptions
parent.title=In-app Billing
parent.link=index.html
page.metaDescription=Subscriptions let you sell content or features in your app with automated, recurring billing.
page.image=/images/play_dev.jpg
-page.tags="inapp, iap, billing"
+page.tags="subscriptions, billing, inapp, iap"
meta.tags="monetization, inappbilling, subscriptions"
@jd:body
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 8a49433..10f5326 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -1,6 +1,7 @@
page.title=Testing In-app Billing
parent.title=In-app Billing
parent.link=index.html
+page.tags="inapp, billing, iap"
@jd:body
<div id="qv-wrapper">
diff --git a/docs/html/google/play/billing/index.jd b/docs/html/google/play/billing/index.jd
index 18b1523..875271fe 100644
--- a/docs/html/google/play/billing/index.jd
+++ b/docs/html/google/play/billing/index.jd
@@ -2,7 +2,7 @@
page.metaDescription=In-app Billing lets you sell digital content as one-time purchases or subscriptions.
page.image=/images/play_dev.jpg
meta.tags="monetizing, inappbilling, subscriptions"
-page.tags="inapp, iap, subscriptions"
+page.tags="billing, inapp, iap"
@jd:body
<p>In-app Billing is a Google Play service that lets you sell digital content from inside
diff --git a/docs/html/google/play/billing/versions.jd b/docs/html/google/play/billing/versions.jd
index 1271a15..dbe3ea3 100644
--- a/docs/html/google/play/billing/versions.jd
+++ b/docs/html/google/play/billing/versions.jd
@@ -1,3 +1,4 @@
+excludeFromSuggestions=true
page.title=In-app Billing Version Notes
@jd:body
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index dbe6c1a..7ebda53 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -111,15 +111,15 @@
<dd>Actual physical size, measured as the screen's diagonal.
<p>For simplicity, Android groups all actual screen sizes into four generalized sizes: small,
-normal, large, and extra large.</p></dd>
+normal, large, and extra-large.</p></dd>
<dt><em>Screen density</em></dt>
<dd>The quantity of pixels within a physical area of the screen; usually referred to as dpi (dots
per inch). For example, a "low" density screen has fewer pixels within a given physical area,
compared to a "normal" or "high" density screen.</p>
- <p>For simplicity, Android groups all actual screen densities into four generalized densities:
-low, medium, high, and extra high.</p></dd>
+ <p>For simplicity, Android groups all actual screen densities into six generalized densities:
+low, medium, high, extra-high, extra-extra-high, and extra-extra-extra-high.</p></dd>
<dt><em>Orientation</em></dt>
<dd>The orientation of the screen from the user's point of view. This is either landscape or
@@ -168,9 +168,15 @@
href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a> for more
information.</p>
</li>
-<li>A set of four generalized <strong>densities</strong>: <em>ldpi</em> (low), <em>mdpi</em>
-(medium),
-<em>hdpi</em> (high), and <em>xhdpi</em> (extra high)
+<li>A set of six generalized <strong>densities</strong>:
+ <ul>
+ <li><em>ldpi</em> (low) ~120dpi</li>
+ <li><em>mdpi</em> (medium) ~160dpi</li>
+ <li><em>hdpi</em> (high) ~240dpi</li>
+ <li><em>xhdpi</em> (extra-high) ~320dpi</li>
+ <li><em>xxhdpi</em> (extra-extra-high) ~480dpi</li>
+ <li><em>xxxhdpi</em> (extra-extra-extra-high) ~640dpi</li>
+ </ul>
</li>
</ul>
@@ -243,14 +249,14 @@
densities.</p>
<p>Maintaining density independence is important because, without it, a UI element (such as a
-button) appears physically larger on a low density screen and smaller on a high density screen. Such
+button) appears physically larger on a low-density screen and smaller on a high-density screen. Such
density-related size changes can cause problems in your application layout and usability. Figures 2
and 3 show the difference between an application when it does not provide density independence and
when it does, respectively.</p>
<img src="{@docRoot}images/screens_support/density-test-bad.png" alt="" />
<p class="img-caption"><strong>Figure 2.</strong> Example application without support for
-different densities, as shown on low, medium, and high density screens.</p>
+different densities, as shown on low, medium, and high-density screens.</p>
<img src="{@docRoot}images/screens_support/density-test-good.png" alt="" />
<p class="img-caption"><strong>Figure 3.</strong> Example application with good support for
@@ -266,8 +272,8 @@
</ul>
<p>In figure 2, the text view and bitmap drawable have dimensions specified in pixels ({@code px}
-units), so the views are physically larger on a low density screen and smaller on a high density
-screen. This is because although the actual screen sizes may be the same, the high density screen
+units), so the views are physically larger on a low-density screen and smaller on a high-density
+screen. This is because although the actual screen sizes may be the same, the high-density screen
has more pixels per inch (the same amount of pixels fit in a smaller area). In figure 3, the layout
dimensions are specified in density-independent pixels ({@code dp} units). Because the baseline for
density-independent pixels is a medium-density screen, the device with a medium-density screen looks
@@ -311,7 +317,7 @@
<a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
<supports-screens>}</a> element in your manifest file.</p>
</li>
-
+
<li><strong>Provide different layouts for different screen sizes</strong>
<p>By default, Android resizes your application layout to fit the current device screen. In most
cases, this works fine. In other cases, your UI might not look as good and might need adjustments
@@ -320,7 +326,7 @@
you might need to adjust sizes so that everything can fit on the screen.</p>
<p>The configuration qualifiers you can use to provide size-specific resources are
<code>small</code>, <code>normal</code>, <code>large</code>, and <code>xlarge</code>. For
-example, layouts for an extra large screen should go in {@code layout-xlarge/}.</p>
+example, layouts for an extra-large screen should go in {@code layout-xlarge/}.</p>
<p>Beginning with Android 3.2 (API level 13), the above size groups are deprecated and you
should instead use the {@code sw<N>dp} configuration qualifier to define the smallest
available width required by your layout resources. For example, if your multi-pane tablet layout
@@ -328,7 +334,7 @@
new techniques for declaring layout resources is discussed further in the section about <a
href="#DeclaringTabletLayouts">Declaring Tablet Layouts for Android 3.2</a>.</p>
</li>
-
+
<li><strong>Provide different bitmap drawables for different screen densities</strong>
<p>By default, Android scales your bitmap drawables ({@code .png}, {@code .jpg}, and {@code
.gif} files) and Nine-Patch drawables ({@code .9.png} files) so that they render at the appropriate
@@ -337,10 +343,22 @@
screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the
bitmaps. To ensure your bitmaps look their best, you should include alternative versions at
different resolutions for different screen densities.</p>
- <p>The configuration qualifiers you can use for density-specific resources are
-<code>ldpi</code> (low), <code>mdpi</code> (medium), <code>hdpi</code> (high), and
-<code>xhdpi</code> (extra high). For example, bitmaps for high-density screens should go in
-{@code drawable-hdpi/}.</p>
+ <p>The <a href="#qualifiers">configuration qualifiers</a> (described in detail below) that you
+can use for density-specific resources are <code>ldpi</code> (low), <code>mdpi</code> (medium),
+<code>hdpi</code> (high), <code>xhdpi</code> extra-high), <code>xxhdpi</code>
+(extra-extra-high), and <code>xxxhdpi</code> (extra-extra-extra-high). For example, bitmaps
+for high-density screens should go in {@code drawable-hdpi/}.</p>
+ <p class="note" id="xxxhdpi-note"><strong>Note:</strong> the <code>drawable-xxxhdpi</code>
+qualifier is necessary only to provide a launcher icon that can appear larger than usual on an
+xxhdpi device. You do not need to provide xxxhdpi assets for all your app's images.</p>
+ <p>Some devices scale-up the launcher icon by as much as 25%. For example, if your highest
+density launcher icon image is already extra-extra-high-density, the scaling process will make it
+appear less crisp. So you should provide a higher density launcher icon in the
+<code>drawable-xxxhdpi</code> directory, which the system uses instead of scaling up a smaller
+version of the icon.</p>
+ <p>See <a href="{@docRoot}design/style/iconography.html#xxxhdpi-launcher">Provide an
+xxx-high-density launcher icon</a> for more information. You should not use the
+<code>xxxhdpi</code> qualifier for UI elements other than the launcher icon.</p>
</li>
</ul>
@@ -371,14 +389,14 @@
<p>The "default" resources are those that are not tagged with a configuration qualifier. For
example, the resources in {@code drawable/} are the default drawable resources. The system
assumes that default resources are designed for the baseline screen size and density, which is a
-normal screen size and a medium density. As such, the system scales default density
+normal screen size and a medium-density. As such, the system scales default density
resources up for high-density screens and down for low-density screens, as appropriate.</p>
<p>However, when the system is looking for a density-specific resource and does not find it in
the density-specific directory, it won't always use the default resources. The system may
instead use one of the other density-specific resources in order to provide better results
when scaling. For example, when looking for a low-density resource and it is not available, the
system prefers to scale-down the high-density version of the resource, because the
-system can easily scale a high-density resource down to low-density by a factor of 0.5, with
+system can easily scale a high-density resource down to low-density by a factor of 0.5, with
fewer artifacts, compared to scaling a medium-density resource by a factor of 0.75.</p>
</li>
</ol>
@@ -416,9 +434,9 @@
files must be named exactly the same as the default resource files.</li>
</ol>
-<p>For example, {@code xlarge} is a configuration qualifier for extra large screens. When you append
+<p>For example, {@code xlarge} is a configuration qualifier for extra-large screens. When you append
this string to a resource directory name (such as {@code layout-xlarge}), it indicates to the
-system that these resources are to be used on devices that have an extra large screen.</p>
+system that these resources are to be used on devices that have an extra-large screen.</p>
<p class="table-caption"><strong>Table 1.</strong> Configuration qualifiers that allow you to
provide special resources for different screen configurations.</p>
@@ -445,11 +463,11 @@
</tr>
<tr>
<td><code>xlarge</code></td>
-<td>Resources for <em>extra large</em> size screens.</td>
+<td>Resources for <em>extra-large</em> size screens.</td>
</tr>
<tr>
-<td rowspan="6">Density</td>
+<td rowspan="8">Density</td>
<td><code>ldpi</code></td>
<td>Resources for low-density (<em>ldpi</em>) screens (~120dpi).</td>
</tr>
@@ -464,7 +482,14 @@
</tr>
<tr>
<td><code>xhdpi</code></td>
-<td>Resources for extra high-density (<em>xhdpi</em>) screens (~320dpi).</td>
+<td>Resources for extra-high-density (<em>xhdpi</em>) screens (~320dpi).</td>
+</tr>
+<td><code>xxhdpi</code></td>
+<td>Resources for extra-extra-high-density (<em>xxhdpi</em>) screens (~480dpi).</td>
+</tr>
+<td><code>xxxhdpi</code></td>
+<td>Resources for extra-extra-extra-high-density (<em>xxxhdpi</em>) uses (~640dpi). Use this for the
+ launcher icon only, see <a href="#xxxhdpi-note">note</a> above.</td>
</tr>
<tr>
<td><code>nodpi</code></td>
@@ -515,18 +540,18 @@
<p>For example, the following is a list of resource directories in an application that
provides different layout designs for different screen sizes and different bitmap drawables
-for medium, high, and extra high density screens.</p>
+for medium, high, and extra-high-density screens.</p>
<pre class="classic">
-res/layout/my_layout.xml // layout for normal screen size ("default")
-res/layout-small/my_layout.xml // layout for small screen size
-res/layout-large/my_layout.xml // layout for large screen size
-res/layout-xlarge/my_layout.xml // layout for extra large screen size
-res/layout-xlarge-land/my_layout.xml // layout for extra large in landscape orientation
+res/layout/my_layout.xml // layout for normal screen size ("default")
+res/layout-large/my_layout.xml // layout for large screen size
+res/layout-xlarge/my_layout.xml // layout for extra-large screen size
+res/layout-xlarge-land/my_layout.xml // layout for extra-large in landscape orientation
-res/drawable-mdpi/my_icon.png // bitmap for medium density
-res/drawable-hdpi/my_icon.png // bitmap for high density
-res/drawable-xhdpi/my_icon.png // bitmap for extra high density
+res/drawable-mdpi/my_icon.png // bitmap for medium-density
+res/drawable-hdpi/my_icon.png // bitmap for high-density
+res/drawable-xhdpi/my_icon.png // bitmap for extra-high-density
+res/drawable-xxhdpi/my_icon.png // bitmap for extra-extra-high-density
</pre>
<p>For more information about how to use alternative resources and a complete list of
@@ -575,10 +600,10 @@
screen. For example, a row of buttons might not fit within the width of the screen on a small screen
device. In this case you should provide an alternative layout for small screens that adjusts the
size or position of the buttons.</li>
- <li>When testing on an extra large screen, you might realize that your layout doesn't make
+ <li>When testing on an extra-large screen, you might realize that your layout doesn't make
efficient use of the big screen and is obviously stretched to fill it.
-In this case, you should provide an alternative layout for extra large screens that provides a
-redesigned UI that is optimized for bigger screens such as tablets.
+In this case, you should provide an alternative layout for extra-large screens that provides a
+redesigned UI that is optimized for bigger screens such as tablets.
<p>Although your application should work fine without an alternative layout on big screens, it's
quite important to users that your application looks as though it's designed specifically for their
devices. If the UI is obviously stretched, users are more likely to be unsatisfied with the
@@ -598,7 +623,7 @@
<p>If your UI uses bitmaps that need to fit the size of a view even after the system scales
the layout (such as the background image for a button), you should use <a
href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">Nine-Patch</a> bitmap files. A
-Nine-Patch file is basically a PNG file in which you specific two-dimensional regions that are
+Nine-Patch file is basically a PNG file in which you specify two-dimensional regions that are
stretchable. When the system needs to scale the view in which the bitmap is used, the system
stretches the Nine-Patch bitmap, but stretches only the specified regions. As such, you don't
need to provide different drawables for different screen sizes, because the Nine-Patch bitmap can
@@ -621,21 +646,24 @@
each one, for different densities.</p>
<p class="note"><strong>Note:</strong> You only need to provide density-specific drawables for
-bitmap files ({@code .png}, {@code .jpg}, or {@code .gif}) and Nine-Path files ({@code
+bitmap files ({@code .png}, {@code .jpg}, or {@code .gif}) and Nine-Patch files ({@code
.9.png}). If you use XML files to define shapes, colors, or other <a
href="{@docRoot}guide/topics/resources/drawable-resource.html">drawable resources</a>, you should
put one copy in the default drawable directory ({@code drawable/}).</p>
<p>To create alternative bitmap drawables for different densities, you should follow the
-<b>3:4:6:8 scaling ratio</b> between the four generalized densities. For example, if you have
-a bitmap drawable that's 48x48 pixels for medium-density screen (the size for a launcher icon),
-all the different sizes should be:</p>
+<b>3:4:6:8:12:16 scaling ratio</b> between the six generalized densities. For example, if you have
+a bitmap drawable that's 48x48 pixels for medium-density screens, all the different sizes should be:
+</p>
<ul>
- <li>36x36 for low-density</li>
- <li>48x48 for medium-density</li>
- <li>72x72 for high-density</li>
- <li>96x96 for extra high-density</li>
+ <li>36x36 (0.75x) for low-density</li>
+ <li>48x48 (1.0x baseline) for medium-density</li>
+ <li>72x72 (1.5x) for high-density</li>
+ <li>96x96 (2.0x) for extra-high-density</li>
+ <li>180x180 (3.0x) for extra-extra-high-density</li>
+ <li>192x192 (4.0x) for extra-extra-extra-high-density (launcher icon only; see
+ <a href="#xxxhdpi-note">note</a> above)</li>
</ul>
<p>For more information about designing icons, see the <a
@@ -715,7 +743,7 @@
screen area. Specifically, the device's smallestWidth is the shortest of the screen's available
height and width (you may also think of it as the "smallest possible width" for the screen). You can
use this qualifier to ensure that, regardless of the screen's current orientation, your
-application's has at least {@code <N>} dps of width available for it UI.</p>
+application's has at least {@code <N>} dps of width available for its UI.</p>
<p>For example, if your layout requires that its smallest dimension of screen area be at
least 600 dp at all times, then you can use this qualifer to create the layout resources, {@code
res/layout-sw600dp/}. The system will use these resources only when the smallest dimension of
@@ -1011,8 +1039,8 @@
<p>If you need to control exactly how your application will look on various
screen configurations, adjust your layouts and bitmap drawables in configuration-specific
resource directories. For example, consider an icon that you want to display on
-medium and high density screens. Simply create your icon at two different sizes
-(for instance 100x100 for medium density and 150x150 for high density) and put
+medium and high-density screens. Simply create your icon at two different sizes
+(for instance 100x100 for medium-density and 150x150 for high-density) and put
the two variations in the appropriate directories, using the proper
qualifiers:</p>
@@ -1115,9 +1143,7 @@
<div class="figure" style="width:300px">
<img src="{@docRoot}images/screens_support/scale-test.png" alt="" />
<p class="img-caption"><strong>Figure 5.</strong> Comparison of pre-scaled and auto-scaled
-bitmaps, from <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/DensityActivity.html">
-ApiDemos</a>.
+bitmaps.
</p>
</div>
@@ -1153,10 +1179,7 @@
(120), medium (160) and high (240) density bitmaps on a high-density screen. The differences are
subtle, because all of the bitmaps are being scaled to match the current screen density, however the
scaled bitmaps have slightly different appearances depending on whether they are pre-scaled or
-auto-scaled at draw time. You can find the source code for this sample application, which
-demonstrates using pre-scaled and auto-scaled bitmaps, in <a
-href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/DensityActivity.html">
-ApiDemos</a>.</p>
+auto-scaled at draw time.</p>
<p class="note"><strong>Note:</strong> In Android 3.0 and above, there should be no perceivable
difference between pre-scaled and auto-scaled bitmaps, due to improvements in the graphics
@@ -1172,9 +1195,9 @@
pixels. Imagine an application in which a scroll or fling gesture is recognized after the user's
finger has moved by at least 16 pixels. On a baseline screen, a user's must move by {@code 16 pixels
/ 160 dpi}, which equals 1/10th of an inch (or 2.5 mm) before the gesture is recognized. On a device
-with a high density display (240dpi), the user's must move by {@code 16 pixels / 240 dpi}, which
+with a high-density display (240dpi), the user's must move by {@code 16 pixels / 240 dpi}, which
equals 1/15th of an inch (or 1.7 mm). The distance is much shorter and the application thus appears
-more sensitive to the user.</p>
+more sensitive to the user.</p>
<p>To fix this issue, the gesture threshold must be expressed in code in <code>dp</code> and then
converted to actual pixels. For example:</p>
@@ -1194,7 +1217,7 @@
<p>The {@link android.util.DisplayMetrics#density DisplayMetrics.density} field specifies the scale
factor you must use to convert {@code dp} units to pixels, according to the current screen density.
On a medium-density screen, {@link android.util.DisplayMetrics#density DisplayMetrics.density}
-equals 1.0; on a high-density screen it equals 1.5; on an extra high-density screen, it equals 2.0;
+equals 1.0; on a high-density screen it equals 1.5; on an extra-high-density screen, it equals 2.0;
and on a low-density screen, it equals 0.75. This figure is the factor by which you should multiply
the {@code dp} units on order to get the actual pixel count for the current screen. (Then add {@code
0.5f} to round the figure up to the nearest whole number, when converting to an integer.) For more
@@ -1277,7 +1300,7 @@
<nobr>High density (240), <em>hdpi</em><nobr>
</th>
<th>
- <nobr>Extra high density (320), <em>xhdpi</em><nobr>
+ <nobr>Extra-high-density (320), <em>xhdpi</em><nobr>
</th>
</tr>
<tr>
@@ -1315,7 +1338,7 @@
</tr>
<tr>
<th>
- <em>Extra Large</em> screen
+ <em>Extra-Large</em> screen
</th>
<td>1024x600</td>
<td><strong>WXGA (1280x800)</strong><sup>†</sup><br>
@@ -1369,4 +1392,4 @@
<p>For more information about creating AVDs from the command line, see <a
href="{@docRoot}tools/devices/managing-avds-cmdline.html">Managing AVDs from the
-Command Line</a></p>
+Command Line</a>.</p>
\ No newline at end of file
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index bf16630..6d9527f 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -389,7 +389,7 @@
<ul>
<li>240x320 ldpi (QVGA handset)</li>
<li>320x480 mdpi (handset)</li>
- <li>480x800 hdpi (high density handset)</li>
+ <li>480x800 hdpi (high-density handset)</li>
</ul>
</li>
<li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
@@ -483,20 +483,20 @@
<ul class="nolist">
<li>{@code small}: Screens that are of similar size to a
low-density QVGA screen. The minimum layout size for a small screen
- is approximately 320x426 dp units. Examples are QVGA low density and VGA high
+ is approximately 320x426 dp units. Examples are QVGA low-density and VGA high
density.</li>
<li>{@code normal}: Screens that are of similar size to a
medium-density HVGA screen. The minimum
layout size for a normal screen is approximately 320x470 dp units. Examples
- of such screens a WQVGA low density, HVGA medium density, WVGA
- high density.</li>
+ of such screens a WQVGA low-density, HVGA medium-density, WVGA
+ high-density.</li>
<li>{@code large}: Screens that are of similar size to a
medium-density VGA screen.
The minimum layout size for a large screen is approximately 480x640 dp units.
- Examples are VGA and WVGA medium density screens.</li>
+ Examples are VGA and WVGA medium-density screens.</li>
<li>{@code xlarge}: Screens that are considerably larger than the traditional
medium-density HVGA screen. The minimum layout size for an xlarge screen
- is approximately 720x960 dp units. In most cases, devices with extra large
+ is approximately 720x960 dp units. In most cases, devices with extra-large
screens would be too large to carry in a pocket and would most likely
be tablet-style devices. <em>Added in API level 9.</em></li>
</ul>
@@ -613,6 +613,8 @@
<code>mdpi</code><br/>
<code>hdpi</code><br/>
<code>xhdpi</code><br/>
+ <code>xxhdpi</code><br/>
+ <code>xxxhdpi</code><br/>
<code>nodpi</code><br/>
<code>tvdpi</code>
</td>
@@ -622,8 +624,14 @@
<li>{@code mdpi}: Medium-density (on traditional HVGA) screens; approximately
160dpi.</li>
<li>{@code hdpi}: High-density screens; approximately 240dpi.</li>
- <li>{@code xhdpi}: Extra high-density screens; approximately 320dpi. <em>Added in API
+ <li>{@code xhdpi}: Extra-high-density screens; approximately 320dpi. <em>Added in API
Level 8</em></li>
+ <li>{@code xxhdpi}: Extra-extra-high-density screens; approximately 480dpi. <em>Added in API
+Level 16</em></li>
+ <li>{@code xxxhdpi}: Extra-extra-extra-high-density uses (launcher icon only, see the
+ <a href="{@docRoot}guide/practices/screens_support.html#xxxhdpi-note">note</a>
+ in <em>Supporting Multiple Screens</em>); approximately 640dpi. <em>Added in API
+Level 18</em></li>
<li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
to match the device density.</li>
<li>{@code tvdpi}: Screens somewhere between mdpi and hdpi; approximately 213dpi. This is
@@ -631,8 +639,9 @@
apps shouldn't need it—providing mdpi and hdpi resources is sufficient for most apps and
the system will scale them as appropriate. This qualifier was introduced with API level 13.</li>
</ul>
- <p>There is a 3:4:6:8 scaling ratio between the four primary densities (ignoring the
-tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
+ <p>There is a 3:4:6:8:12:16 scaling ratio between the six primary densities (ignoring the
+tvdpi density). So, a 9x9 bitmap in ldpi is 12x12 in mdpi, 18x18 in hdpi, 24x24 in xhdpi and so on.
+</p>
<p>If you decide that your image resources don't look good enough on a television or
other certain devices and want to try tvdpi resources, the scaling factor is 1.33*mdpi. For
example, a 100px x 100px image for mdpi screens should be 133px x 133px for tvdpi.</p>
diff --git a/docs/html/images/tools/projectview01.png b/docs/html/images/tools/projectview01.png
new file mode 100644
index 0000000..90589fb
--- /dev/null
+++ b/docs/html/images/tools/projectview01.png
Binary files differ
diff --git a/docs/html/images/tools/projectview03.png b/docs/html/images/tools/projectview03.png
new file mode 100644
index 0000000..f527ff1
--- /dev/null
+++ b/docs/html/images/tools/projectview03.png
Binary files differ
diff --git a/docs/html/reference/renderscript/rs__matrix_8rsh.html b/docs/html/reference/renderscript/rs__matrix_8rsh.html
index 69cc373..3b8e047 100644
--- a/docs/html/reference/renderscript/rs__matrix_8rsh.html
+++ b/docs/html/reference/renderscript/rs__matrix_8rsh.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<title>/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh File Reference</title>
+<title>frameworks/rs/scriptc/rs_matrix.rsh File Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
@@ -27,18 +27,18 @@
<div class="summary">
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
-<div class="title">/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh File Reference</div> </div>
+<div class="title">frameworks/rs/scriptc/rs_matrix.rsh File Reference</div> </div>
</div>
<div class="contents">
<table class="memberdecls">
<tr><td colspan="2"><h2><a name="func-members"></a>
Functions</h2></td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ab69543f85a673f23fbb5f893e5824395">rsMatrixSet</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a0a85c8d3607f1b75019f6991c5b19fca">rsMatrixSet</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, float v)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad485084684991796cffdd8a008557569">rsMatrixGet</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top">float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aaa86b029d5c5c15fead5338bba02e4c3">rsMatrixGet</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a08a247cdf2e70e78310bf04f9ecd5144">rsMatrixSet</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#af9707d7be5945bf55ed53683624176ff">rsMatrixSet</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, float v)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#acfebfc7b97e7282b78cd9c65b791932a">rsMatrixGet</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME float </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a683b4537b98103c50cc66780dfe8cd69">rsMatrixGet</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a5b31e83553efa947db2198674d5db043">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad2954a5ac11d2370227296be89e92471">rsMatrixLoadIdentity</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m)</td></tr>
@@ -65,9 +65,9 @@
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float left, float right, float bottom, float top, float near, float far)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float left, float right, float bottom, float top, float near, float far)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, float fovy, float aspect, float near, float far)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a2f11c3d7cc34ddce90ba785b93af8da2">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a88ae2ed203769cb4a7917f84f6c1a2e2">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in)</td></tr>
-<tr><td class="memItemLeft" align="right" valign="top"><a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a8d81a7143d5d45f60f7e91f955579bab">rsMatrixMultiply</a> (const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a47b6abbf32ffaf77bb13d96c3f05779f">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m, <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a716bc2d29b80eb25388aba3ba8845aef">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> *m, <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in)</td></tr>
+<tr><td class="memItemLeft" align="right" valign="top">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m, <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">bool </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a> (<a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> *m)</td></tr>
@@ -75,16 +75,30 @@
<tr><td class="memItemLeft" align="right" valign="top">void </td><td class="memItemRight" valign="bottom"><a class="el" href="rs__matrix_8rsh.html#a49164dd4d4e85b212196028b1fd89dc1">rsMatrixTranspose</a> (<a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> *m)</td></tr>
</table>
<hr/><a name="details" id="details"></a><h2>Detailed Description</h2>
-<div class="textblock"><p>Matrix routines. </p>
+<div class="textblock"><p>Matrix functions. </p>
+<p>These functions let you manipulate square matrices of rank 2x2, 3x3, and 4x4. They are particularly useful for graphical transformations and are compatible with OpenGL.</p>
+<p>A few general notes:</p>
+<ul>
+<li>We use a zero-based index for rows and columns. E.g. the last element of a <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> is found at (3, 3).</li>
+</ul>
+<ul>
+<li>RenderScript uses column-based vectors. Transforming a vector is done by postmultiplying the vector, e.g. <em>(matrix * vector)</em>, as provided by <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</li>
+</ul>
+<ul>
+<li>To create a transformation matrix that performs two transformations at once, multiply the two source matrices, with the first transformation as the right argument. E.g. to create a transformation matrix that applies the transformation <em>s1</em> followed by <em>s2</em>, call rsMatrixLoadMultiply(&combined, &s2, &s1). This derives from <em>s2 * (s1 * v)</em>, which is <em>(s2 * s1) * v</em>.</li>
+</ul>
+<ul>
+<li>We have two style of functions to create transformation matrices: rsMatrixLoad<em>Transformation</em> and rsMatrix<em>Transformation</em>. The former style simply stores the transformation matrix in the first argument. The latter modifies a pre-existing transformation matrix so that the new transformation happens first. E.g. if you call <a class="el" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a> on a matrix that already does a scaling, the resulting matrix when applied to a vector will first do the translation then the scaling. </li>
+</ul>
<p>Definition in file <a class="el" href="rs__matrix_8rsh_source.html">rs_matrix.rsh</a>.</p>
</div><hr/><h2>Function Documentation</h2>
-<a class="anchor" id="a22e983b67d3089c5cb97032e249ca335"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="a22e983b67d3089c5cb97032e249ca335" args="(const rs_matrix4x4 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="af26fdbf8b8f0ed5d1b53f62b2aef5110"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="af26fdbf8b8f0ed5d1b53f62b2aef5110" args="(const rs_matrix4x4 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -93,13 +107,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -109,25 +123,26 @@
</table>
</div>
<div class="memdoc">
-<p>Get one element of a matrix.</p>
+<p>Returns one element of a matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>The matrix to read from </td></tr>
- <tr><td class="paramname">row</td><td></td></tr>
- <tr><td class="paramname">col</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to extract the element from. </td></tr>
+ <tr><td class="paramname">col</td><td>The zero-based column of the element to be extracted. </td></tr>
+ <tr><td class="paramname">row</td><td>The zero-based row of the element to extracted.</td></tr>
</table>
</dd>
</dl>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>The order of the column and row parameters may be unexpected.</dd></dl>
<dl class="return"><dt><b>Returns:</b></dt><dd>float </dd></dl>
</div>
</div>
-<a class="anchor" id="ad485084684991796cffdd8a008557569"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="ad485084684991796cffdd8a008557569" args="(const rs_matrix3x3 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="acfebfc7b97e7282b78cd9c65b791932a"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="acfebfc7b97e7282b78cd9c65b791932a" args="(const rs_matrix3x3 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -136,13 +151,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -156,12 +171,12 @@
</div>
</div>
-<a class="anchor" id="aaa86b029d5c5c15fead5338bba02e4c3"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="aaa86b029d5c5c15fead5338bba02e4c3" args="(const rs_matrix2x2 *m, uint32_t row, uint32_t col)" -->
+<a class="anchor" id="a683b4537b98103c50cc66780dfe8cd69"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixGet" ref="a683b4537b98103c50cc66780dfe8cd69" args="(const rs_matrix2x2 *m, uint32_t col, uint32_t row)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">float rsMatrixGet </td>
+ <td class="memname">_RS_RUNTIME float rsMatrixGet </td>
<td>(</td>
<td class="paramtype">const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -170,13 +185,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em> </td>
+ <td class="paramname"><em>row</em> </td>
</tr>
<tr>
<td></td>
@@ -204,10 +219,11 @@
</table>
</div>
<div class="memdoc">
-<p>Returns true if the matrix was successfully inversed</p>
+<p>Inverts a matrix in place.</p>
+<p>Returns true if the matrix was successfully inversed.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to invert. </td></tr>
</table>
</dd>
</dl>
@@ -228,10 +244,11 @@
</table>
</div>
<div class="memdoc">
-<p>Returns true if the matrix was successfully inversed and transposed.</p>
+<p>Inverts and transpose a matrix in place.</p>
+<p>The matrix is first inverted then transposed. Returns true if the matrix was successfully inverted.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
</table>
</dd>
</dl>
@@ -263,9 +280,11 @@
</div>
<div class="memdoc">
<p>Set the elements of a matrix from an array of floats.</p>
+<p>The array of floats should be in row-major order, i.e. the element a <em>row 0, column 0</em> should be first, followed by the element at <em>row 0, column 1</em>, etc.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">v</td><td>The array of values to set the matrix to. These arrays should be 4, 9, or 16 floats long, depending on the matrix size. </td></tr>
</table>
</dd>
</dl>
@@ -352,7 +371,20 @@
</table>
</div>
<div class="memdoc">
-<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
+<p>Set the elements of a matrix from another matrix.</p>
+<p>If the source matrix is smaller than the destination, the rest of the destination is filled with elements of the identity matrix. E.g. loading a <a class="el" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> into a <a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> will give:</p>
+ <table>
+ <tr><td>m00</td><td>m01</td><td>0.0</td><td>0.0</td></tr>
+ <tr><td>m10</td><td>m11</td><td>0.0</td><td>0.0</td></tr>
+ <tr><td>0.0</td><td>0.0</td><td>1.0</td><td>0.0</td></tr>
+ <tr><td>0.0</td><td>0.0</td><td>0.0</td><td>1.0</td></tr>
+ </table><dl><dt><b>Parameters:</b></dt><dd>
+ <table class="params">
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">v</td><td>The source matrix. </td></tr>
+ </table>
+ </dd>
+</dl>
</div>
</div>
@@ -408,13 +440,7 @@
</table>
</div>
<div class="memdoc">
-<p>Set the elements of a matrix from another matrix.</p>
-<dl><dt><b>Parameters:</b></dt><dd>
- <table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- </table>
- </dd>
-</dl>
+<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
</div>
</div>
@@ -528,10 +554,13 @@
</table>
</div>
<div class="memdoc">
-<p>Load an Frustum projection matrix constructed from the 6 planes</p>
+<p>Load a frustum projection matrix.</p>
+<p>Constructs a frustum projection matrix, transforming the box identified by the six clipping planes <em>left, right, bottom, top, near, far</em>.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">left</td><td></td></tr>
<tr><td class="paramname">right</td><td></td></tr>
<tr><td class="paramname">bottom</td><td></td></tr>
@@ -561,7 +590,7 @@
<p>Set the elements of a matrix to the identity matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
</table>
</dd>
</dl>
@@ -634,12 +663,15 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply two matrix (lhs, rhs) and place the result in m.</p>
+<p>Multiply two matrices.</p>
+<p>Sets <em>m</em> to the matrix product of <em>lhs * rhs</em>.</p>
+<p>To combine two 4x4 transformaton matrices, multiply the second transformation matrix by the first transformation matrix. E.g. to create a transformation matrix that applies the transformation <em>s1</em> followed by <em>s2</em>, call rsMatrixLoadMultiply(&combined, &s2, &s1).</p>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>As of version 21, storing the result back into right matrix is not supported and will result in undefined behavior. Use rsMatrixMulitply instead. E.g. instead of doing rsMatrixLoadMultiply (&m2r, &m2r, &m2l), use rsMatrixMultiply (&m2r, &m2l). rsMatrixLoadMultiply (&m2l, &m2r, &m2l) works as expected.</dd></dl>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">lhs</td><td></td></tr>
- <tr><td class="paramname">rhs</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">lhs</td><td>The left matrix of the product. </td></tr>
+ <tr><td class="paramname">rhs</td><td>The right matrix of the product. </td></tr>
</table>
</dd>
</dl>
@@ -768,10 +800,13 @@
</table>
</div>
<div class="memdoc">
-<p>Load an Ortho projection matrix constructed from the 6 planes</p>
+<p>Load an orthographic projection matrix.</p>
+<p>Constructs an orthographic projection matrix, transforming the box identified by the six clipping planes <em>left, right, bottom, top, near, far</em> into a unit cube with a corner at <em>(-1, -1, -1)</em> and the opposite at <em>(1, 1, 1)</em>.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://en.wikipedia.org/wiki/Orthographic_projection">https://en.wikipedia.org/wiki/Orthographic_projection</a> and <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">left</td><td></td></tr>
<tr><td class="paramname">right</td><td></td></tr>
<tr><td class="paramname">bottom</td><td></td></tr>
@@ -826,14 +861,17 @@
</table>
</div>
<div class="memdoc">
-<p>Load an perspective projection matrix constructed from the 6 planes</p>
+<p>Load a perspective projection matrix.</p>
+<p>Constructs a perspective projection matrix, assuming a symmetrical field of view.</p>
+<p>To apply this projection to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf">https://www.opengl.org/documentation/specs/version2.0/glspec20.pdf</a></p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
<tr><td class="paramname">fovy</td><td>Field of view, in degrees along the Y axis. </td></tr>
<tr><td class="paramname">aspect</td><td>Ratio of x / y. </td></tr>
- <tr><td class="paramname">near</td><td></td></tr>
- <tr><td class="paramname">far</td><td></td></tr>
+ <tr><td class="paramname">near</td><td>The near clipping plane. </td></tr>
+ <tr><td class="paramname">far</td><td>The far clipping plane. </td></tr>
</table>
</dd>
</dl>
@@ -883,13 +921,16 @@
</div>
<div class="memdoc">
<p>Load a rotation matrix.</p>
+<p>This function creates a rotation matrix. The axis of rotation is the <em>(x, y, z)</em> vector.</p>
+<p>To rotate a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
+<p>See <a href="http://en.wikipedia.org/wiki/Rotation_matrix">http://en.wikipedia.org/wiki/Rotation_matrix</a> .</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">rot</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">rot</td><td>How much rotation to do, in degrees. </td></tr>
+ <tr><td class="paramname">x</td><td>The x component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">y</td><td>The y component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">z</td><td>The z component of the vector that is the axis of rotation. </td></tr>
</table>
</dd>
</dl>
@@ -933,12 +974,14 @@
</div>
<div class="memdoc">
<p>Load a scale matrix.</p>
+<p>This function creates a scaling matrix, where each component of a vector is multiplied by a number. This number can be negative.</p>
+<p>To scale a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">x</td><td>The multiple to scale the x components by. </td></tr>
+ <tr><td class="paramname">y</td><td>The multiple to scale the y components by. </td></tr>
+ <tr><td class="paramname">z</td><td>The multiple to scale the z components by. </td></tr>
</table>
</dd>
</dl>
@@ -982,12 +1025,14 @@
</div>
<div class="memdoc">
<p>Load a translation matrix.</p>
+<p>This function creates a translation matrix, where a number is added to each element of a vector.</p>
+<p>To translate a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to set. </td></tr>
+ <tr><td class="paramname">x</td><td>The number to add to each x component. </td></tr>
+ <tr><td class="paramname">y</td><td>The number to add to each y component. </td></tr>
+ <tr><td class="paramname">z</td><td>The number to add to each z component. </td></tr>
</table>
</dd>
</dl>
@@ -1018,11 +1063,13 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply the matrix m by rhs and place the result back into m.</p>
+<p>Multiply a matrix into another one.</p>
+<p>Sets <em>m</em> to the matrix product <em>m * rhs</em>.</p>
+<p>When combining two 4x4 transformation matrices using this function, the resulting matrix will correspond to performing the <em>rhs</em> transformation first followed by the original <em>m</em> transformation.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>(lhs) </td></tr>
- <tr><td class="paramname">rhs</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The left matrix of the product and the matrix to be set. </td></tr>
+ <tr><td class="paramname">rhs</td><td>The right matrix of the product. </td></tr>
</table>
</dd>
</dl>
@@ -1085,14 +1132,14 @@
</div>
</div>
-<a class="anchor" id="a2f11c3d7cc34ddce90ba785b93af8da2"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a2f11c3d7cc34ddce90ba785b93af8da2" args="(const rs_matrix4x4 *m, float4 in)" -->
+<a class="anchor" id="a47b6abbf32ffaf77bb13d96c3f05779f"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a47b6abbf32ffaf77bb13d96c3f05779f" args="(rs_matrix4x4 *m, float4 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1109,19 +1156,24 @@
</table>
</div>
<div class="memdoc">
-<p>Multiply a vector by a matrix and return the result vector. API version 14+</p>
+<p>Multiply a vector by a matrix.</p>
+<p>Returns the post-multiplication of the vector by the matrix, ie. <em>m * in</em>.</p>
+<p>When multiplying a <em>float3</em> to a <em><a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a></em>, the vector is expanded with (1).</p>
+<p>When multiplying a <em>float2</em> to a <em><a class="el" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a></em>, the vector is expanded with (0, 1).</p>
+<p>When multiplying a <em>float2</em> to a <em><a class="el" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a></em>, the vector is expanded with (0).</p>
+<p>This function is available in API version 10-13. Starting with API 14, the function takes a const matrix as the first argument.</p>
<p>This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. </p>
</div>
</div>
-<a class="anchor" id="a88ae2ed203769cb4a7917f84f6c1a2e2"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a88ae2ed203769cb4a7917f84f6c1a2e2" args="(const rs_matrix3x3 *m, float3 in)" -->
+<a class="anchor" id="a716bc2d29b80eb25388aba3ba8845aef"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a716bc2d29b80eb25388aba3ba8845aef" args="(rs_matrix3x3 *m, float3 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1142,14 +1194,14 @@
</div>
</div>
-<a class="anchor" id="a8d81a7143d5d45f60f7e91f955579bab"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a8d81a7143d5d45f60f7e91f955579bab" args="(const rs_matrix2x2 *m, float2 in)" -->
+<a class="anchor" id="a4d9a8bb7c3f5d67b14fa349bdd531d13"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixMultiply" ref="a4d9a8bb7c3f5d67b14fa349bdd531d13" args="(rs_matrix2x2 *m, float2 in)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname"><a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> rsMatrixMultiply </td>
+ <td class="memname">_RS_RUNTIME <a class="el" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> rsMatrixMultiply </td>
<td>(</td>
- <td class="paramtype">const <a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
+ <td class="paramtype"><a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
</tr>
<tr>
@@ -1212,14 +1264,16 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a rotation matrix</p>
+<p>Multiply the matrix <em>m</em> with a rotation matrix.</p>
+<p>This function modifies a transformation matrix to first do a rotation. The axis of rotation is the <em>(x, y, z)</em> vector.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">rot</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">rot</td><td>How much rotation to do, in degrees. </td></tr>
+ <tr><td class="paramname">x</td><td>The x component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">y</td><td>The y component of the vector that is the axis of rotation. </td></tr>
+ <tr><td class="paramname">z</td><td>The z component of the vector that is the axis of rotation. </td></tr>
</table>
</dd>
</dl>
@@ -1262,25 +1316,27 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a scale matrix</p>
+<p>Multiply the matrix <em>m</em> with a scaling matrix.</p>
+<p>This function modifies a transformation matrix to first do a scaling. When scaling, each component of a vector is multiplied by a number. This number can be negative.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">x</td><td>The multiple to scale the x components by. </td></tr>
+ <tr><td class="paramname">y</td><td>The multiple to scale the y components by. </td></tr>
+ <tr><td class="paramname">z</td><td>The multiple to scale the z components by. </td></tr>
</table>
</dd>
</dl>
</div>
</div>
-<a class="anchor" id="ad6ea242218e0f1a031f754df0317e6e7"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="ad6ea242218e0f1a031f754df0317e6e7" args="(rs_matrix4x4 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="aca88832ed720e301780152c60884393e"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="aca88832ed720e301780152c60884393e" args="(rs_matrix4x4 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix4x4.html">rs_matrix4x4</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1289,13 +1345,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1311,26 +1367,27 @@
</table>
</div>
<div class="memdoc">
-<p>Set one element of a matrix.</p>
+<p>Set an element of a matrix.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td>The matrix to be set </td></tr>
- <tr><td class="paramname">row</td><td></td></tr>
- <tr><td class="paramname">col</td><td></td></tr>
- <tr><td class="paramname">v</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix that will be modified. </td></tr>
+ <tr><td class="paramname">col</td><td>The zero-based column of the element to be set. </td></tr>
+ <tr><td class="paramname">row</td><td>The zero-based row of the element to be set. </td></tr>
+ <tr><td class="paramname">v</td><td>The value to set.</td></tr>
</table>
</dd>
</dl>
+<dl class="warning"><dt><b>Warning:</b></dt><dd>The order of the column and row parameters may be unexpected.</dd></dl>
<dl class="return"><dt><b>Returns:</b></dt><dd>void </dd></dl>
</div>
</div>
-<a class="anchor" id="ab69543f85a673f23fbb5f893e5824395"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="ab69543f85a673f23fbb5f893e5824395" args="(rs_matrix3x3 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="a08a247cdf2e70e78310bf04f9ecd5144"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="a08a247cdf2e70e78310bf04f9ecd5144" args="(rs_matrix3x3 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix3x3.html">rs_matrix3x3</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1339,13 +1396,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1365,12 +1422,12 @@
</div>
</div>
-<a class="anchor" id="a0a85c8d3607f1b75019f6991c5b19fca"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="a0a85c8d3607f1b75019f6991c5b19fca" args="(rs_matrix2x2 *m, uint32_t row, uint32_t col, float v)" -->
+<a class="anchor" id="af9707d7be5945bf55ed53683624176ff"></a><!-- doxytag: member="rs_matrix.rsh::rsMatrixSet" ref="af9707d7be5945bf55ed53683624176ff" args="(rs_matrix2x2 *m, uint32_t col, uint32_t row, float v)" -->
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
- <td class="memname">void rsMatrixSet </td>
+ <td class="memname">_RS_RUNTIME void rsMatrixSet </td>
<td>(</td>
<td class="paramtype"><a class="el" href="structrs__matrix2x2.html">rs_matrix2x2</a> * </td>
<td class="paramname"><em>m</em>, </td>
@@ -1379,13 +1436,13 @@
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>row</em>, </td>
+ <td class="paramname"><em>col</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype"><a class="el" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> </td>
- <td class="paramname"><em>col</em>, </td>
+ <td class="paramname"><em>row</em>, </td>
</tr>
<tr>
<td class="paramkey"></td>
@@ -1441,13 +1498,15 @@
</table>
</div>
<div class="memdoc">
-<p>Multiple matrix m with a translation matrix</p>
+<p>Multiply the matrix <em>m</em> with a translation matrix.</p>
+<p>This function modifies a transformation matrix to first do a translation. When translating, a number is added to each component of a vector.</p>
+<p>To apply this combined transformation to a vector, multiply the vector by the created matrix using <a class="el" href="rs__matrix_8rsh.html#a4d9a8bb7c3f5d67b14fa349bdd531d13">rsMatrixMultiply</a>.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
- <tr><td class="paramname">x</td><td></td></tr>
- <tr><td class="paramname">y</td><td></td></tr>
- <tr><td class="paramname">z</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to modify. </td></tr>
+ <tr><td class="paramname">x</td><td>The number to add to each x component. </td></tr>
+ <tr><td class="paramname">y</td><td>The number to add to each y component. </td></tr>
+ <tr><td class="paramname">z</td><td>The number to add to each z component. </td></tr>
</table>
</dd>
</dl>
@@ -1468,10 +1527,10 @@
</table>
</div>
<div class="memdoc">
-<p>Transpose the matrix m.</p>
+<p>Transpose the matrix m in place.</p>
<dl><dt><b>Parameters:</b></dt><dd>
<table class="params">
- <tr><td class="paramname">m</td><td></td></tr>
+ <tr><td class="paramname">m</td><td>The matrix to transpose. </td></tr>
</table>
</dd>
</dl>
diff --git a/docs/html/reference/renderscript/rs__matrix_8rsh_source.html b/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
index c1aaeb2..77144bd 100644
--- a/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
+++ b/docs/html/reference/renderscript/rs__matrix_8rsh_source.html
@@ -3,7 +3,7 @@
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
-<title>/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh Source File</title>
+<title>frameworks/rs/scriptc/rs_matrix.rsh Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
@@ -24,7 +24,7 @@
</div>
<div class="header">
<div class="headertitle">
-<div class="title">/usr/local/google/home/srhines/android_trees/jb-mr2-dev/frameworks/rs/scriptc/rs_matrix.rsh</div> </div>
+<div class="title">frameworks/rs/scriptc/rs_matrix.rsh</div> </div>
</div>
<div class="contents">
<a href="rs__matrix_8rsh.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
@@ -43,129 +43,128 @@
<a name="l00014"></a>00014 <span class="comment"> * limitations under the License.</span>
<a name="l00015"></a>00015 <span class="comment"> */</span>
<a name="l00016"></a>00016
-<a name="l00023"></a>00023 <span class="preprocessor">#ifndef __RS_MATRIX_RSH__</span>
-<a name="l00024"></a>00024 <span class="preprocessor"></span><span class="preprocessor">#define __RS_MATRIX_RSH__</span>
-<a name="l00025"></a>00025 <span class="preprocessor"></span>
-<a name="l00036"></a>00036 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00037"></a>00037 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00041"></a>00041 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00042"></a>00042 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00046"></a>00046 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00047"></a>00047 <a class="code" href="rs__matrix_8rsh.html#ad6ea242218e0f1a031f754df0317e6e7">rsMatrixSet</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <span class="keywordtype">float</span> v);
-<a name="l00048"></a>00048
-<a name="l00058"></a>00058 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00059"></a>00059 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00063"></a>00063 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00064"></a>00064 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00068"></a>00068 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
-<a name="l00069"></a>00069 <a class="code" href="rs__matrix_8rsh.html#a22e983b67d3089c5cb97032e249ca335">rsMatrixGet</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col);
-<a name="l00070"></a>00070
-<a name="l00076"></a>00076 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00080"></a>00080 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
-<a name="l00084"></a>00084 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
-<a name="l00085"></a>00085
-<a name="l00091"></a>00091 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00095"></a>00095 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00099"></a>00099 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <span class="keywordtype">float</span> *v);
-<a name="l00103"></a>00103 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *v);
-<a name="l00107"></a>00107 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
-<a name="l00108"></a>00108
-<a name="l00114"></a>00114 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
-<a name="l00118"></a>00118 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
-<a name="l00122"></a>00122 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
-<a name="l00123"></a>00123
-<a name="l00133"></a>00133 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00134"></a>00134 <a class="code" href="rs__matrix_8rsh.html#a268032f3ac6d766b1d7fe72a6cb50464">rsMatrixLoadRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00135"></a>00135
-<a name="l00144"></a>00144 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00145"></a>00145 <a class="code" href="rs__matrix_8rsh.html#acaf51d1f9ad5041ce01fbf8b7c5923fd">rsMatrixLoadScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00146"></a>00146
-<a name="l00155"></a>00155 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00156"></a>00156 <a class="code" href="rs__matrix_8rsh.html#a1b521c8a3d1260fa732cbf0a71af0e74">rsMatrixLoadTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00157"></a>00157
-<a name="l00165"></a>00165 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00166"></a>00166 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *lhs, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
-<a name="l00170"></a>00170 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00171"></a>00171 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *lhs, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
-<a name="l00175"></a>00175 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00176"></a>00176 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *lhs, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
-<a name="l00177"></a>00177
-<a name="l00184"></a>00184 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00185"></a>00185 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
-<a name="l00189"></a>00189 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00190"></a>00190 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
-<a name="l00194"></a>00194 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00195"></a>00195 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
-<a name="l00196"></a>00196
-<a name="l00206"></a>00206 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00207"></a>00207 <a class="code" href="rs__matrix_8rsh.html#ad5ed05ca4880397fb29615e3c6798de1">rsMatrixRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00208"></a>00208
-<a name="l00217"></a>00217 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00218"></a>00218 <a class="code" href="rs__matrix_8rsh.html#a94cc6b22bd1a6c07a9a1c1d21afb392c">rsMatrixScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00219"></a>00219
-<a name="l00228"></a>00228 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00229"></a>00229 <a class="code" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
-<a name="l00230"></a>00230
-<a name="l00242"></a>00242 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00243"></a>00243 <a class="code" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00244"></a>00244
-<a name="l00256"></a>00256 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00257"></a>00257 <a class="code" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00258"></a>00258
-<a name="l00268"></a>00268 extern <span class="keywordtype">void</span> __attribute__((overloadable))
-<a name="l00269"></a>00269 <a class="code" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a>* m, <span class="keywordtype">float</span> fovy, <span class="keywordtype">float</span> aspect, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
-<a name="l00270"></a>00270
-<a name="l00271"></a>00271 <span class="preprocessor">#if !defined(RS_VERSION) || (RS_VERSION < 14)</span>
-<a name="l00272"></a>00272 <span class="preprocessor"></span>
-<a name="l00276"></a>00276 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00277"></a>00277 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
-<a name="l00278"></a>00278
-<a name="l00282"></a>00282 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00283"></a>00283 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00050"></a>00050 <span class="preprocessor">#ifndef __RS_MATRIX_RSH__</span>
+<a name="l00051"></a>00051 <span class="preprocessor"></span><span class="preprocessor">#define __RS_MATRIX_RSH__</span>
+<a name="l00052"></a>00052 <span class="preprocessor"></span>
+<a name="l00066"></a>00066 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00067"></a>00067 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00071"></a>00071 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00072"></a>00072 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00076"></a>00076 _RS_RUNTIME <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00077"></a>00077 <a class="code" href="rs__matrix_8rsh.html#aca88832ed720e301780152c60884393e">rsMatrixSet</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row, <span class="keywordtype">float</span> v);
+<a name="l00078"></a>00078
+<a name="l00091"></a>00091 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00092"></a>00092 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00096"></a>00096 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00097"></a>00097 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00101"></a>00101 _RS_RUNTIME <span class="keywordtype">float</span> __attribute__((overloadable))
+<a name="l00102"></a>00102 <a class="code" href="rs__matrix_8rsh.html#af26fdbf8b8f0ed5d1b53f62b2aef5110">rsMatrixGet</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> col, <a class="code" href="rs__types_8rsh.html#a435d1572bf3f880d55459d9805097f62">uint32_t</a> row);
+<a name="l00103"></a>00103
+<a name="l00109"></a>00109 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00113"></a>00113 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
+<a name="l00117"></a>00117 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a0ffd9de971cf10d0a663ff565be8d3cc">rsMatrixLoadIdentity</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
+<a name="l00118"></a>00118
+<a name="l00130"></a>00130 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00134"></a>00134 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00138"></a>00138 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <span class="keywordtype">float</span> *v);
+<a name="l00156"></a>00156 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *v);
+<a name="l00160"></a>00160 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
+<a name="l00164"></a>00164 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
+<a name="l00168"></a>00168 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *v);
+<a name="l00172"></a>00172 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac380c4117e047da494a74f0dad20fab3">rsMatrixLoad</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *v);
+<a name="l00173"></a>00173
+<a name="l00191"></a>00191 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00192"></a>00192 <a class="code" href="rs__matrix_8rsh.html#a268032f3ac6d766b1d7fe72a6cb50464">rsMatrixLoadRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00193"></a>00193
+<a name="l00208"></a>00208 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00209"></a>00209 <a class="code" href="rs__matrix_8rsh.html#acaf51d1f9ad5041ce01fbf8b7c5923fd">rsMatrixLoadScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00210"></a>00210
+<a name="l00225"></a>00225 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00226"></a>00226 <a class="code" href="rs__matrix_8rsh.html#a1b521c8a3d1260fa732cbf0a71af0e74">rsMatrixLoadTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00227"></a>00227
+<a name="l00247"></a>00247 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00248"></a>00248 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *lhs, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
+<a name="l00252"></a>00252 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00253"></a>00253 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *lhs, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
+<a name="l00257"></a>00257 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00258"></a>00258 <a class="code" href="rs__matrix_8rsh.html#a79f14c4c0f5ecc1bbd0bf54da8b653ef">rsMatrixLoadMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *lhs, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
+<a name="l00259"></a>00259
+<a name="l00272"></a>00272 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00273"></a>00273 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *rhs);
+<a name="l00277"></a>00277 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00278"></a>00278 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *rhs);
+<a name="l00282"></a>00282 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00283"></a>00283 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *rhs);
<a name="l00284"></a>00284
-<a name="l00288"></a>00288 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00289"></a>00289 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00290"></a>00290
-<a name="l00294"></a>00294 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00295"></a>00295 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00296"></a>00296
-<a name="l00300"></a>00300 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00301"></a>00301 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00300"></a>00300 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00301"></a>00301 <a class="code" href="rs__matrix_8rsh.html#ad5ed05ca4880397fb29615e3c6798de1">rsMatrixRotate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> rot, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
<a name="l00302"></a>00302
-<a name="l00306"></a>00306 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
-<a name="l00307"></a>00307 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00308"></a>00308 <span class="preprocessor">#else</span>
-<a name="l00309"></a>00309 <span class="preprocessor"></span>
-<a name="l00313"></a>00313 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00314"></a>00314 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
-<a name="l00315"></a>00315
-<a name="l00319"></a>00319 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00320"></a>00320 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00321"></a>00321
-<a name="l00325"></a>00325 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
-<a name="l00326"></a>00326 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00327"></a>00327
-<a name="l00331"></a>00331 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00332"></a>00332 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
-<a name="l00333"></a>00333
-<a name="l00337"></a>00337 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
-<a name="l00338"></a>00338 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00339"></a>00339
-<a name="l00343"></a>00343 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
-<a name="l00344"></a>00344 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
-<a name="l00345"></a>00345 <span class="preprocessor">#endif</span>
-<a name="l00346"></a>00346 <span class="preprocessor"></span>
-<a name="l00347"></a>00347
-<a name="l00353"></a>00353 <span class="keyword">extern</span> <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00354"></a>00354
-<a name="l00360"></a>00360 extern <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00361"></a>00361
-<a name="l00367"></a>00367 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
-<a name="l00371"></a>00371 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
-<a name="l00375"></a>00375 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
-<a name="l00376"></a>00376
-<a name="l00377"></a>00377
-<a name="l00378"></a>00378 <span class="preprocessor">#endif</span>
+<a name="l00318"></a>00318 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00319"></a>00319 <a class="code" href="rs__matrix_8rsh.html#a94cc6b22bd1a6c07a9a1c1d21afb392c">rsMatrixScale</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00320"></a>00320
+<a name="l00336"></a>00336 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00337"></a>00337 <a class="code" href="rs__matrix_8rsh.html#a4df5f9b5bb6044f3c3426f2f58b94405">rsMatrixTranslate</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> x, <span class="keywordtype">float</span> y, <span class="keywordtype">float</span> z);
+<a name="l00338"></a>00338
+<a name="l00361"></a>00361 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00362"></a>00362 <a class="code" href="rs__matrix_8rsh.html#a4c59884a0e534dbbcdc5655842732d43">rsMatrixLoadOrtho</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00363"></a>00363
+<a name="l00384"></a>00384 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00385"></a>00385 <a class="code" href="rs__matrix_8rsh.html#ad25760aaf01e95d0055237afab41bbb3">rsMatrixLoadFrustum</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <span class="keywordtype">float</span> left, <span class="keywordtype">float</span> right, <span class="keywordtype">float</span> bottom, <span class="keywordtype">float</span> top, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00386"></a>00386
+<a name="l00403"></a>00403 extern <span class="keywordtype">void</span> __attribute__((overloadable))
+<a name="l00404"></a>00404 <a class="code" href="rs__matrix_8rsh.html#aa404c34d7478f2921f7415d2da95d02b">rsMatrixLoadPerspective</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a>* m, <span class="keywordtype">float</span> fovy, <span class="keywordtype">float</span> aspect, <span class="keywordtype">float</span> near, <span class="keywordtype">float</span> far);
+<a name="l00405"></a>00405
+<a name="l00406"></a>00406 <span class="preprocessor">#if !defined(RS_VERSION) || (RS_VERSION < 14)</span>
+<a name="l00407"></a>00407 <span class="preprocessor"></span>
+<a name="l00421"></a>00421 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00422"></a>00422 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
+<a name="l00423"></a>00423
+<a name="l00427"></a>00427 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00428"></a>00428 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00429"></a>00429
+<a name="l00433"></a>00433 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00434"></a>00434 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00435"></a>00435
+<a name="l00439"></a>00439 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00440"></a>00440 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00441"></a>00441
+<a name="l00445"></a>00445 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00446"></a>00446 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00447"></a>00447
+<a name="l00451"></a>00451 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
+<a name="l00452"></a>00452 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00453"></a>00453 <span class="preprocessor">#else</span>
+<a name="l00454"></a>00454 <span class="preprocessor"></span>
+<a name="l00467"></a>00467 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00468"></a>00468 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> in);
+<a name="l00469"></a>00469
+<a name="l00473"></a>00473 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00474"></a>00474 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00475"></a>00475
+<a name="l00479"></a>00479 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#adb5162dc168ddd471d948faa60b37c5e">float4</a> __attribute__((overloadable))
+<a name="l00480"></a>00480 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00481"></a>00481
+<a name="l00485"></a>00485 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00486"></a>00486 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> in);
+<a name="l00487"></a>00487
+<a name="l00491"></a>00491 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a0046fa0f208d0899adbcf1f8b5aafadd">float3</a> __attribute__((overloadable))
+<a name="l00492"></a>00492 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00493"></a>00493
+<a name="l00497"></a>00497 _RS_RUNTIME <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> __attribute__((overloadable))
+<a name="l00498"></a>00498 <a class="code" href="rs__matrix_8rsh.html#a97953ab2606900a839e5816c619abe66">rsMatrixMultiply</a>(const <a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m, <a class="code" href="rs__types_8rsh.html#a5086d0fcb71f916c936af486ccf0dd41">float2</a> in);
+<a name="l00499"></a>00499 <span class="preprocessor">#endif</span>
+<a name="l00500"></a>00500 <span class="preprocessor"></span>
+<a name="l00501"></a>00501
+<a name="l00509"></a>00509 <span class="keyword">extern</span> <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a00b6a334ba5ac94d84850f22ec9f4de5">rsMatrixInverse</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00510"></a>00510
+<a name="l00519"></a>00519 extern <span class="keywordtype">bool</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#ac05080d52da2d99a759ef34fa0655e82">rsMatrixInverseTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00520"></a>00520
+<a name="l00526"></a>00526 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix4x4.html" title="4x4 float matrix">rs_matrix4x4</a> *m);
+<a name="l00530"></a>00530 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix3x3.html" title="3x3 float matrix">rs_matrix3x3</a> *m);
+<a name="l00534"></a>00534 extern <span class="keywordtype">void</span> __attribute__((overloadable)) <a class="code" href="rs__matrix_8rsh.html#a88095c70f1550c760844b3e32e41a31a">rsMatrixTranspose</a>(<a class="code" href="structrs__matrix2x2.html" title="2x2 float matrix">rs_matrix2x2</a> *m);
+<a name="l00535"></a>00535
+<a name="l00536"></a>00536
+<a name="l00537"></a>00537 <span class="preprocessor">#endif</span>
</pre></div></div>
</div>
diff --git a/docs/html/sdk/installing/studio-androidview.jd b/docs/html/sdk/installing/studio-androidview.jd
new file mode 100644
index 0000000..09aeaba
--- /dev/null
+++ b/docs/html/sdk/installing/studio-androidview.jd
@@ -0,0 +1,55 @@
+page.title=Using the Android Project View
+
+@jd:body
+
+
+<p>The Android project view in Android Studio shows a flattened version of your project's structure
+that provides quick access to the key source files of Android projects and helps you work with
+the new <a href="{@docRoot}sdk/installing/studio-build.html">Gradle-based build system</a>. The
+Android project view:</p>
+
+<ul>
+<li>Groups the build files for all modules at the top level of the project hierarchy.</li>
+<li>Shows the most important source directories at the top level of the module hierarchy.</li>
+<li>Groups all the manifest files for each module.</li>
+<li>Shows resource files from all Gradle source sets.</li>
+<li>Groups resource files for different locales, orientations, and screen types in a single group
+per resource type.</li>
+</ul>
+
+<div style="float:right;margin-left:30px;width:240px">
+<img src="{@docRoot}images/tools/projectview01.png" alt="" width="220" height="264"/>
+<p class="img-caption"><strong>Figure 1:</strong> Show the Android project view.</p>
+</div>
+
+
+<h2 id="enable-view">Enable the Android Project View</h2>
+
+<p>The Android project view is not yet enabled by default. To show the Android project view,
+click <strong>Project</strong> and select <strong>Android</strong>, as shown in Figure 1.</p>
+
+
+<h2 id="project-view">Use the Android Project View</h2>
+
+<p>The Android project view shows all the build files at the top level of the project hierarchy
+under <strong>Gradle Scripts</strong>. Each project module appears as a folder at the top
+level of the project hierarchy and contains these three elements at the top level:</p>
+
+<ul>
+<li><code>java/</code> - Source files for the module.</li>
+<li><code>manifests/</code> - Manifest files for the module.</li>
+<li><code>res/</code> - Resource files for the module.</li>
+</ul>
+
+<p>Figure 2 shows how the Android project view groups all the instances of the
+<code>ic_launcher.png</code> resource for different screen densities under the same element.</p>
+
+<p class="note"><strong>Note:</strong> The Android project view shows a hierarchy that helps you
+work with Android projects by providing a flattened structure that highlights the most commonly
+used files while developing Android applications. However, the project structure on disk differs
+from this representation.</p>
+
+<img src="{@docRoot}images/tools/projectview03.png" alt=""
+ style="margin-top:10px" width="650" height="508"/>
+<p class="img-caption"><strong>Figure 2:</strong> The traditional project view (left) and the
+Android project view (right).</p>
\ No newline at end of file
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index 71b15d5..e75f451 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -2,59 +2,59 @@
page.template=sdk
-ndk.mac64_download=android-ndk32-r10-darwin-x86_64.tar.bz2
-ndk.mac64_bytes=411610468
-ndk.mac64_checksum=3ce1fa3dbe7a188f5d2640fd2f7ca944
+ndk.mac64_download=android-ndk32-r10b-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=413652124
+ndk.mac64_checksum=7ca4a84e9c56c38acdafb007e7cd33c5
-ndk.mac32_download=android-ndk32-r10-darwin-x86.tar.bz2
-ndk.mac32_bytes=404768263
-ndk.mac32_checksum=1824eec1f6749b6cb7bb306a3b924c33
+ndk.mac32_download=android-ndk32-r10b-darwin-x86.tar.bz2
+ndk.mac32_bytes=406998070
+ndk.mac32_checksum=db3626b2c5f3245d90e2724f7bcf4c3e
-ndk.linux64_download=android-ndk32-r10-linux-x86_64.tar.bz2
-ndk.linux64_bytes=420671390
-ndk.linux64_checksum=e3ff629d212a8106a43415862fa39baf
+ndk.linux64_download=android-ndk32-r10b-linux-x86_64.tar.bz2
+ndk.linux64_bytes=422237011
+ndk.linux64_checksum=5c0f301aa789a1a747d5d2aeb8c69ef3
-ndk.linux32_download=android-ndk32-r10-linux-x86.tar.bz2
-ndk.linux32_bytes=420078216
-ndk.linux32_checksum=8d9a5faa6e77b43bfae0f169079b21c4
+ndk.linux32_download=android-ndk32-r10b-linux-x86.tar.bz2
+ndk.linux32_bytes=421052081
+ndk.linux32_checksum=e8f55daa5c9de7ab79aaaf5d7d751b69
-ndk.win64_download=android-ndk32-r10-windows-x86_64.zip
-ndk.win64_bytes=529850429
-ndk.win64_checksum=b11f9239344f7c377ed5b627f0fb236e
+ndk.win64_download=android-ndk32-r10b-windows-x86_64.zip
+ndk.win64_bytes=531912027
+ndk.win64_checksum=e4dd2e0c6f38e3ad936c366bdf6b1d4e
-ndk.win32_download=android-ndk32-r10-windows-x86.zip
-ndk.win32_bytes=500135685
-ndk.win32_checksum=0a3c01147abba945cc4ef5837519ec97
+ndk.win32_download=android-ndk32-r10b-windows-x86.zip
+ndk.win32_bytes=502720425
+ndk.win32_checksum=9fa4f19bca7edd6eefa63fe788737987
-ndk.mac64_64_download=android-ndk64-r10-darwin-x86_64.tar.bz2
-ndk.mac64_64_bytes=327740247
-ndk.mac64_64_checksum=72561b27acc6192a2e81b345ea128a20
+ndk.mac64_64_download=android-ndk64-r10b-darwin-x86_64.tar.bz2
+ndk.mac64_64_bytes=346423776
+ndk.mac64_64_checksum=5bae7feed20ebf0762c0baefe6b84b6d
-ndk.mac32_64_download=android-ndk64-r10-darwin-x86.tar.bz2
-ndk.mac32_64_bytes=323736411
-ndk.mac32_64_checksum=5bbaf9d8051ba5d2c0fff74cfd87c374
+ndk.mac32_64_download=android-ndk64-r10b-darwin-x86.tar.bz2
+ndk.mac32_64_bytes=344052876
+ndk.mac32_64_checksum=4447049ac2b5877176b9b6b1cf3bcdb2
-ndk.linux64_64_download=android-ndk64-r10-linux-x86_64.tar.bz2
-ndk.linux64_64_bytes=339708042
-ndk.linux64_64_checksum=737290195583268b7fbff4aa56465ab6
+ndk.linux64_64_download=android-ndk64-r10b-linux-x86_64.tar.bz2
+ndk.linux64_64_bytes=358835298
+ndk.linux64_64_checksum=2aa12a0d9a70bcab83e42d010a685136
-ndk.linux32_64_download=android-ndk64-r10-linux-x86.tar.bz2
-ndk.linux32_64_bytes=338544906
-ndk.linux32_64_checksum=bea5d027baeb948cbff6af840d26b80d
+ndk.linux32_64_download=android-ndk64-r10b-linux-x86.tar.bz2
+ndk.linux32_64_bytes=358060577
+ndk.linux32_64_checksum=b77eb583626d8c7f5c11e49181fd5eac
-ndk.win64_64_download=android-ndk64-r10-windows-x86_64.zip
-ndk.win64_64_bytes=417411195
-ndk.win64_64_checksum=91879ec85539b45313a21b9526b911a8
+ndk.win64_64_download=android-ndk64-r10b-windows-x86_64.zip
+ndk.win64_64_bytes=437152652
+ndk.win64_64_checksum=df39185e6c5a4d72eb9fca3f9aaabc46
-ndk.win32_64_download=android-ndk64-r10-windows-x86.zip
-ndk.win32_64_bytes=396751892
-ndk.win32_64_checksum=f79070ace2cde9ebf6a2e2be4a61ac7a
+ndk.win32_64_download=android-ndk64-r10b-windows-x86.zip
+ndk.win32_64_bytes=417290468
+ndk.win32_64_checksum=0f0324cb11f04e8b2641e5422ee39c81
-ndk.debug_info_download=android-ndk-r10-cxx-stl-libs-with-debug-info.zip
-ndk.debug_info_bytes=253198908
-ndk.debug_info_checksum=c2a90c43d17dbb5f0609cc8237491788
+ndk.debug_info_download=android-ndk-r10b-cxx-stl-libs-with-debug-info.zip
+ndk.debug_info_bytes=227302317
+ndk.debug_info_checksum=bed1bb855a41bdb572a804dbf6d45aa6
page.title=Android NDK
@@ -357,15 +357,6 @@
</div>
</div>
-
-
-
-
-
-
-
-
-
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
@@ -418,7 +409,7 @@
<p>With NDK revision 9 and higher, the release packages have been split to reduce download size.
- The first download for each platform contains the default NDK toolchain. The second download
+ The first download for each platform contains the default NDK toolchain. The additional download
contains legacy NDK toolchains for that platform, which is only required if you are not using
the current, recommended toolchain for your NDK builds.</p>
@@ -426,10 +417,91 @@
<p>The following sections provide information about releases of the NDK.</p>
+
<div class="toggle-content opened">
<p>
<a href="#" onclick="return toggleContent(this)"> <img
src="/assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+ >Android NDK, Revision 10b</a> <em>(September 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <dl>
+
+ <dt>Important notes:</dt>
+ <dd>
+ <ul>
+ <li>Because of the 512MB size restriction on downloadable packages, the following 32-bit items are not in the 32-bit NDK download packages. Instead, they reside in the 64-bit ones:</li>
+ <ul>
+ <li>Android-L headers</li>
+ <li>GCC 4.9</li>
+ </ul>
+ <li>Currently, the only Renderscript support provided by the NDK is for 32-bit Renderscript with Android 4.4 (API level 19). You cannot build HelloComputeNDK (the only Renderscript sample) with any other combination of Renderscript (32- or 64-bit) and Android version.</li>
+ <li>To compile native-codec, you must use a 64-bit NDK package, which is where all the Android-L headers are located. </li>
+ </ul>
+ </dd>
+
+
+ <dt>Important bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed gdb 7.6 in GCC 4.8/4.9. (Issues <a href="http://b.android.com/74112">74112</a> and <a href="http://b.android.com/74371">74371</a>.)</li>
+ <li>Fixed GCC 4.8/4.9 for x86, so that they no longer enable <code>-msse4.2</code> and <code>-mpopcnt</code> by default. (Issue <a href="http://b.android.com/73843">73843</a>.)</li>
+ </ul>
+ </dd>
+
+ <dt>Other bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Removed <code>stdio.h</code> from the <code>include-fixed/</code> directories of all versions of GCC. (Issue <a href="http://b.android.com/73728">73728</a>.)</li>
+ <li>Removed duplicate header files from the Windows packages in the <code>platforms/android-L/arch-*/usr/include/linux/netfilter*/</code> directories. (Issue <a href="https://code.google.com/p/android/issues/detail?id=73704">73704</a>.)</li>
+ <li>Fixed a problem that prevented Clang from building HelloComputeNDK.</li>
+ <li>Fixed atexit. (Issue <a href="http://b.android.com/66595">66595</a>.)</li>
+ <li>Made various fixes to the docs in <code>docs/</code> and <code>sources/third_party/googletest/README.NDK</code>. (Issue <a href="http://b.android.com/74069">74069</a>.)</li>
+ <li>Made the following fixes to the Android-L headers:</li>
+ <ol>
+ <li>Added the following functions to <code>ctype.h</code> and <code>wchar.h</code>: <code>dn_expand()</code>, <code>grantpt()</code>, <code> inet_nsap_addr()</code>, <code>inet_nsap_ntoa()</code>, <code>insque()</code>, <code>nsdispatch()</code>, <code>posix_openpt()</code>, <code>__pthread_cleanup_pop()</code>, <code>__pthread_cleanup_push()</code>, <code>remque()</code>, <code>setfsgid()</code>, <code>setfsuid()</code>, <code>splice()</code>, <code>tee()</code>, <code>twalk()</code> (Issue <a href = "http://b.android.com/73719">73719</a>), and 42 <code>*_l()</code> functions.</li>
+
+ <li>Renamed <code>cmsg_nxthdr</code> to <code>__cmsg_nxthdr</code>.</li>
+
+ <li>Removed <code>__libc_malloc_dispatch</code>.</li>
+
+ <li>Changed the <code>ptrace()</code> prototype to <code>long ptrace(int, ...);</code>.</li>
+
+ <li>Removed <code>sha1.h</code>.</li>
+
+ <li>Extended <code>android_dlextinfo</code> in <code>android/dlext.h</code>.</li>
+
+ <li>Annotated <code>__NDK_FPABI__</code> for functions receiving or returning float- or double-type values in <code>stdlib.h</code>, <code>time.h</code>, <code>wchar.h</code>, and <code>complex.h</code>.</li>
+ </ol>
+ </ul>
+ </dd>
+
+ <dt>Other changes:</dt>
+ <dd>
+ <ul>
+ <li>Updated <code>mipsel-linux-android-4.9</code> and <code>mips64el-linux-android-4.9</code>, implementing a new multilib directory layout, and providing support for gdb-7.7</li>
+ <li>Enhanced <code>cpu-features</code> to detect more arm64 features. (Change list <a href="https://android-review.googlesource.com/#/c/100339">100339</a>.)</li>
+ </dd>
+ </ul>
+
+
+
+ </dl>
+ </div>
+</div>
+
+
+
+
+
+
+
+
+
+<div class="toggle-content closed">
+ <p>
+ <a href="#" onclick="return toggleContent(this)"> <img
+ src="/assets/images/triangle-closed.png" class="toggle-content-img" alt=""
>Android NDK, Revision 10</a> <em>(July 2014)</em>
</p>
<div class="toggle-content-toggleme">
@@ -442,7 +514,7 @@
<li>GCC 4.9 is the default compiler for 64-bit ABIs. Clang is currently version 3.4.
<code>NDK_TOOLCHAIN_VERSION=clang</code>
may not work for arm64-v8a and mips64.</li>
- <li>Android API level L is the first level with 64-bit support. Note that this API
+ <li>Android-L is the first level with 64-bit support. Note that this API
level is a temporary one, and only for L-preview. An actual API level number will replace it at
L-release.</li>
<li>This release includes now includes <code>all32</code> and <code>all64</code>
@@ -479,7 +551,7 @@
<li>For ndk-build, enable 32-bit, GCC 4.9 building either by adding
<code>NDK_TOOLCHAIN_VERSION=4.9</code> to <code>Application.mk</code>, or exporting it as an
environment variable from the command line.</li>
- <li>For a standalone toolchain, use the <code> --toolchain=</code> option in the
+ <li>For a standalone toolchain, use the <code>--toolchain=</code> option in the
<code>make-standalone-toolchain.sh</code> script. For example: <code>--toolchain=arm-linux-androideabi-4.9.</code></li>
</ul>
<li>Upgraded GDB to version 7.6 in GCC 4.8/4.9 and x86*. Since GDB is still at version GDB-7.3.x in
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 93e5976..8eb9cbf 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -24,6 +24,8 @@
Creating a Project</a></li>
<li><a href="<?cs var:toroot ?>sdk/installing/studio-tips.html">
Tips and Tricks</a></li>
+ <li><a href="<?cs var:toroot ?>sdk/installing/studio-androidview.html">
+ Using the Android Project View</a></li>
<li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
Using the Layout Editor</a></li>
<li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
diff --git a/docs/html/wear/images/partners/sony.png b/docs/html/wear/images/partners/sony.png
index 3e9483e..e097fbb 100644
--- a/docs/html/wear/images/partners/sony.png
+++ b/docs/html/wear/images/partners/sony.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index c9a5cff..c372395 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -229,8 +229,7 @@
<img src="/wear/images/partners/samsung.png" alt="Samsung">
</div>
<div class="col-4">
- <img src="/wear/images/partners/sony.png" alt="Sony"
- style="margin-left:57px;margin-top:17px;">
+ <img src="/wear/images/partners/sony.png" alt="Sony">
</div>
</div>
</div> <!-- end .wrap -->
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f18694b..0927ffd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -203,7 +203,7 @@
*/
public void setBitmap(@Nullable Bitmap bitmap) {
if (isHardwareAccelerated()) {
- throw new RuntimeException("Can't set a bitmap device on a GL canvas");
+ throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
}
if (bitmap == null) {
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 5aa7c6a..d28c3d5 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,6 +122,11 @@
* @param canvas The picture is drawn to this canvas
*/
public void draw(Canvas canvas) {
+ if (canvas.isHardwareAccelerated()) {
+ throw new IllegalArgumentException(
+ "Picture playback is only supported on software canvas.");
+ }
+
if (mRecordingCanvas != null) {
endRecording();
}
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index c078c1c..705f5e6 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -60,6 +60,8 @@
* @see Color
* @see #getColor()
* @see #getMode()
+ *
+ * @hide
*/
public void setColor(int color) {
mColor = color;
@@ -84,6 +86,8 @@
* @see PorterDuff
* @see #getMode()
* @see #getColor()
+ *
+ * @hide
*/
public void setMode(PorterDuff.Mode mode) {
mMode = mode;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 5a3e3a3..3cb5210 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -470,19 +470,6 @@
}
/**
- * Specifies a tint and blending mode for this drawable.
- * <p>
- * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
- * tint.
- *
- * @param tint Color state list to use for tinting this drawable, or null to
- * clear the tint
- * @param tintMode A Porter-Duff blending mode
- * @hide TODO: Was in L-preview, remove this API for release
- */
- public void setTint(ColorStateList tint, PorterDuff.Mode tintMode) {}
-
- /**
* Specifies a tint for this drawable.
* <p>
* Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index cd919a6..6f95f91 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
@@ -58,7 +59,7 @@
private final Rect mBounds;
/** Full-opacity color for drawing this ripple. */
- private int mColor;
+ private int mColorOpaque;
/** Maximum ripple radius. */
private float mOuterRadius;
@@ -120,7 +121,7 @@
}
public void setup(int maxRadius, int color, float density) {
- mColor = color | 0xFF000000;
+ mColorOpaque = color | 0xFF000000;
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
mHasMaxRadius = true;
@@ -236,6 +237,9 @@
if (N > 0) {
cancelHardwareAnimations(false);
+ // We canceled old animations, but we're about to run new ones.
+ mHardwareAnimating = true;
+
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
pendingAnimations.get(i).start();
@@ -253,9 +257,8 @@
private boolean drawSoftware(Canvas c, Paint p) {
boolean hasContent = false;
- // Cache the paint alpha so we can restore it later.
- final int paintAlpha = p.getAlpha();
- final int alpha = (int) (paintAlpha * mOpacity + 0.5f);
+ p.setColor(mColorOpaque);
+ final int alpha = (int) (255 * mOpacity + 0.5f);
final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
if (alpha > 0 && radius > 0) {
final float x = MathUtils.lerp(
@@ -268,8 +271,6 @@
hasContent = true;
}
- p.setAlpha(paintAlpha);
-
return hasContent;
}
@@ -369,7 +370,7 @@
final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
final Paint paint = getTempPaint();
paint.setAntiAlias(true);
- paint.setColor(mColor);
+ paint.setColor(mColorOpaque);
paint.setAlpha((int) (255 * mOpacity + 0.5f));
paint.setStyle(Style.FILL);
mPropPaint = CanvasProperty.createPaint(paint);
@@ -402,6 +403,12 @@
mHardwareAnimating = true;
+ // Set up the software values to match the hardware end values.
+ mOpacity = 0;
+ mTweenX = 1;
+ mTweenY = 1;
+ mTweenRadius = 1;
+
invalidateSelf();
}
@@ -412,46 +419,32 @@
public void jump() {
mCanceled = true;
endSoftwareAnimations();
- endHardwareAnimations();
+ cancelHardwareAnimations(true);
mCanceled = false;
}
private void endSoftwareAnimations() {
if (mAnimRadius != null) {
mAnimRadius.end();
+ mAnimRadius = null;
}
if (mAnimOpacity != null) {
mAnimOpacity.end();
+ mAnimOpacity = null;
}
if (mAnimX != null) {
mAnimX.end();
+ mAnimX = null;
}
if (mAnimY != null) {
mAnimY.end();
+ mAnimY = null;
}
}
- private void endHardwareAnimations() {
- final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
- final int N = runningAnimations.size();
- for (int i = 0; i < N; i++) {
- runningAnimations.get(i).end();
- }
- runningAnimations.clear();
-
- // Abort any pending animations. Since we always have a completion
- // listener on a pending animation, we also need to remove ourselves.
- if (!mPendingAnimations.isEmpty()) {
- mPendingAnimations.clear();
- removeSelf();
- }
-
- mHardwareAnimating = false;
- }
-
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
@@ -506,18 +499,22 @@
private void cancelSoftwareAnimations() {
if (mAnimRadius != null) {
mAnimRadius.cancel();
+ mAnimRadius = null;
}
if (mAnimOpacity != null) {
mAnimOpacity.cancel();
+ mAnimOpacity = null;
}
if (mAnimX != null) {
mAnimX.cancel();
+ mAnimX = null;
}
if (mAnimY != null) {
mAnimY.cancel();
+ mAnimY = null;
}
}
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 4e68a60..bc6f5fb 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
@@ -46,8 +47,6 @@
private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f;
- private static final long RIPPLE_ENTER_DELAY = 80;
-
// Hardware animators.
private final ArrayList<RenderNodeAnimator> mRunningAnimations =
new ArrayList<RenderNodeAnimator>();
@@ -60,7 +59,10 @@
private final Rect mBounds;
/** Full-opacity color for drawing this ripple. */
- private int mColor;
+ private int mColorOpaque;
+
+ /** Maximum alpha value for drawing this ripple. */
+ private int mColorAlpha;
/** Maximum ripple radius. */
private float mOuterRadius;
@@ -103,7 +105,8 @@
}
public void setup(int maxRadius, int color, float density) {
- mColor = color | 0xFF000000;
+ mColorOpaque = color | 0xFF000000;
+ mColorAlpha = Color.alpha(color);
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
mHasMaxRadius = true;
@@ -159,6 +162,11 @@
return hasContent;
}
+ public boolean shouldDraw() {
+ final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
+ return mCanUseHardware && mHardwareAnimating || outerAlpha > 0 && mOuterRadius > 0;
+ }
+
private boolean drawHardware(HardwareCanvas c) {
// If we have any pending hardware animations, cancel any running
// animations and start those now.
@@ -167,6 +175,9 @@
if (N > 0) {
cancelHardwareAnimations(false);
+ // We canceled old animations, but we're about to run new ones.
+ mHardwareAnimating = true;
+
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
pendingAnimations.get(i).start();
@@ -184,10 +195,8 @@
private boolean drawSoftware(Canvas c, Paint p) {
boolean hasContent = false;
- // Cache the paint alpha so we can restore it later.
- final int paintAlpha = p.getAlpha();
-
- final int outerAlpha = (int) (paintAlpha * mOuterOpacity + 0.5f);
+ p.setColor(mColorOpaque);
+ final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
if (outerAlpha > 0 && mOuterRadius > 0) {
p.setAlpha(outerAlpha);
p.setStyle(Style.FILL);
@@ -195,8 +204,6 @@
hasContent = true;
}
- p.setAlpha(paintAlpha);
-
return hasContent;
}
@@ -248,25 +255,25 @@
// Determine at what time the inner and outer opacity intersect.
// inner(t) = mOpacity - t * WAVE_OPACITY_DECAY_VELOCITY / 1000
// outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000
- final int outerInflection = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
+ final int inflectionDuration = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
/ (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f));
- final int inflectionOpacity = (int) (255 * (mOuterOpacity + outerInflection
- * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
+ final int inflectionOpacity = (int) (mColorAlpha * (mOuterOpacity
+ + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
if (mCanUseHardware) {
- exitHardware(opacityDuration, outerInflection, inflectionOpacity);
+ exitHardware(opacityDuration, inflectionDuration, inflectionOpacity);
} else {
- exitSoftware(opacityDuration, outerInflection, inflectionOpacity);
+ exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
}
}
- private void exitHardware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+ private void exitHardware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
mPendingAnimations.clear();
final Paint outerPaint = getTempPaint();
outerPaint.setAntiAlias(true);
- outerPaint.setColor(mColor);
- outerPaint.setAlpha((int) (255 * mOuterOpacity + 0.5f));
+ outerPaint.setColor(mColorOpaque);
+ outerPaint.setAlpha((int) (mColorAlpha * mOuterOpacity + 0.5f));
outerPaint.setStyle(Style.FILL);
mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
@@ -274,21 +281,21 @@
mPropOuterY = CanvasProperty.createFloat(mOuterY);
final RenderNodeAnimator outerOpacityAnim;
- if (outerInflection > 0) {
+ if (inflectionDuration > 0) {
// Outer opacity continues to increase for a bit.
- outerOpacityAnim = new RenderNodeAnimator(
- mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
- outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim = new RenderNodeAnimator(mPropOuterPaint,
+ RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
+ outerOpacityAnim.setDuration(inflectionDuration);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
- final int outerDuration = opacityDuration - outerInflection;
+ final int outerDuration = opacityDuration - inflectionDuration;
if (outerDuration > 0) {
final RenderNodeAnimator outerFadeOutAnim = new RenderNodeAnimator(
mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
outerFadeOutAnim.setDuration(outerDuration);
outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
- outerFadeOutAnim.setStartDelay(outerInflection);
+ outerFadeOutAnim.setStartDelay(inflectionDuration);
outerFadeOutAnim.setStartValue(inflectionOpacity);
outerFadeOutAnim.addListener(mAnimationListener);
@@ -320,32 +327,16 @@
*/
public void jump() {
endSoftwareAnimations();
- endHardwareAnimations();
+ cancelHardwareAnimations(true);
}
private void endSoftwareAnimations() {
if (mAnimOuterOpacity != null) {
mAnimOuterOpacity.end();
+ mAnimOuterOpacity = null;
}
}
- private void endHardwareAnimations() {
- final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
- final int N = runningAnimations.size();
- for (int i = 0; i < N; i++) {
- runningAnimations.get(i).end();
- }
- runningAnimations.clear();
-
- // Abort any pending animations. Since we always have a completion
- // listener on a pending animation, we also need to remove ourselves.
- if (!mPendingAnimations.isEmpty()) {
- mPendingAnimations.clear();
- }
-
- mHardwareAnimating = false;
- }
-
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
@@ -353,18 +344,18 @@
return mTempPaint;
}
- private void exitSoftware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+ private void exitSoftware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
final ObjectAnimator outerOpacityAnim;
- if (outerInflection > 0) {
+ if (inflectionDuration > 0) {
// Outer opacity continues to increase for a bit.
outerOpacityAnim = ObjectAnimator.ofFloat(this,
"outerOpacity", inflectionOpacity / 255.0f);
outerOpacityAnim.setAutoCancel(true);
- outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim.setDuration(inflectionDuration);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
- final int outerDuration = opacityDuration - outerInflection;
+ final int outerDuration = opacityDuration - inflectionDuration;
if (outerDuration > 0) {
outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -413,6 +404,7 @@
private void cancelSoftwareAnimations() {
if (mAnimOuterOpacity != null) {
mAnimOuterOpacity.cancel();
+ mAnimOuterOpacity = null;
}
}
@@ -444,14 +436,4 @@
mHardwareAnimating = false;
}
};
-
- /**
- * Interpolator with a smooth log deceleration
- */
- private static final class LogInterpolator implements TimeInterpolator {
- @Override
- public float getInterpolation(float input) {
- return 1 - (float) Math.pow(400, -input * 1.4);
- }
- }
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fa762b7..b05fb61 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -242,7 +242,7 @@
@Override
protected boolean onStateChange(int[] stateSet) {
- super.onStateChange(stateSet);
+ final boolean changed = super.onStateChange(stateSet);
boolean enabled = false;
boolean pressed = false;
@@ -263,19 +263,7 @@
setRippleActive(enabled && pressed);
setBackgroundActive(focused || (enabled && pressed));
- // Update the paint color. Only applicable when animated in software.
- if (mRipplePaint != null && mState.mColor != null) {
- final ColorStateList stateList = mState.mColor;
- final int newColor = stateList.getColorForState(stateSet, 0);
- final int oldColor = mRipplePaint.getColor();
- if (oldColor != newColor) {
- mRipplePaint.setColor(newColor);
- invalidateSelf();
- return true;
- }
- }
-
- return false;
+ return changed;
}
private void setRippleActive(boolean active) {
@@ -587,6 +575,10 @@
ripples[i].onHotspotBoundsChanged();
}
+ if (mRipple != null) {
+ mRipple.onHotspotBoundsChanged();
+ }
+
if (mBackground != null) {
mBackground.onHotspotBoundsChanged();
}
@@ -617,17 +609,23 @@
final boolean drawNonMaskContent = mLayerState.mNum > (hasMask ? 1 : 0);
final boolean drawMask = hasMask && mMask.getOpacity() != PixelFormat.OPAQUE;
final Rect bounds = getDirtyBounds();
+ final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(bounds);
// If we have content, draw it into a layer first.
- final int contentLayer = drawNonMaskContent ?
- drawContentLayer(canvas, bounds, SRC_OVER) : -1;
+ final int contentLayer;
+ if (drawNonMaskContent) {
+ contentLayer = drawContentLayer(canvas, bounds, SRC_OVER);
+ } else {
+ contentLayer = -1;
+ }
// Next, try to draw the ripples (into a layer if necessary). If we need
// to mask against the underlying content, set the xfermode to SRC_ATOP.
final PorterDuffXfermode xfermode = (hasMask || !drawNonMaskContent) ? SRC_OVER : SRC_ATOP;
// If we have a background and a non-opaque mask, draw the masking layer.
- final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode);
+ final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode, drawMask);
if (backgroundLayer >= 0) {
if (drawMask) {
drawMaskingLayer(canvas, bounds, DST_IN);
@@ -644,10 +642,13 @@
canvas.restoreToCount(rippleLayer);
}
- // Composite the layers if needed.
- if (contentLayer >= 0) {
- canvas.restoreToCount(contentLayer);
+ // If we failed to draw anything, at least draw a color so that
+ // invalidation works correctly.
+ if (contentLayer < 0 && backgroundLayer < 0 && rippleLayer < 0) {
+ canvas.drawColor(Color.TRANSPARENT);
}
+
+ canvas.restoreToCount(saveCount);
}
/**
@@ -711,81 +712,29 @@
return restoreToCount;
}
- private int drawBackgroundLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
- // Separate the ripple color and alpha channel. The alpha will be
- // applied when we merge the ripples down to the canvas.
- final int rippleARGB;
- if (mState.mColor != null) {
- rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
- } else {
- rippleARGB = Color.TRANSPARENT;
+ private int drawBackgroundLayer(
+ Canvas canvas, Rect bounds, PorterDuffXfermode mode, boolean drawMask) {
+ int saveCount = -1;
+
+ if (mBackground != null && mBackground.shouldDraw()) {
+ // TODO: We can avoid saveLayer here if we push the xfermode into
+ // the background's render thread animator at exit() time.
+ if (drawMask || mode != SRC_OVER) {
+ saveCount = canvas.saveLayer(bounds.left, bounds.top, bounds.right,
+ bounds.bottom, getMaskingPaint(mode));
+ }
+
+ final float x = mHotspotBounds.exactCenterX();
+ final float y = mHotspotBounds.exactCenterY();
+ canvas.translate(x, y);
+ mBackground.draw(canvas, getRipplePaint());
+ canvas.translate(-x, -y);
}
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- final int rippleAlpha = Color.alpha(rippleARGB);
- final Paint ripplePaint = mRipplePaint;
- ripplePaint.setColor(rippleARGB);
- ripplePaint.setAlpha(0xFF);
-
- boolean drewRipples = false;
- int restoreToCount = -1;
- int restoreTranslate = -1;
-
- // Draw background.
- final RippleBackground background = mBackground;
- if (background != null) {
- // If we're masking the ripple layer, make sure we have a layer
- // first. This will merge SRC_OVER (directly) onto the canvas.
- final Paint maskingPaint = getMaskingPaint(mode);
- maskingPaint.setAlpha(rippleAlpha);
- restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
- bounds.right, bounds.bottom, maskingPaint);
-
- restoreTranslate = canvas.save();
- // Translate the canvas to the current hotspot bounds.
- canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
-
- drewRipples = background.draw(canvas, ripplePaint);
- }
-
- // Always restore the translation.
- if (restoreTranslate >= 0) {
- canvas.restoreToCount(restoreTranslate);
- }
-
- // If we created a layer with no content, merge it immediately.
- if (restoreToCount >= 0 && !drewRipples) {
- canvas.restoreToCount(restoreToCount);
- restoreToCount = -1;
- }
-
- return restoreToCount;
+ return saveCount;
}
private int drawRippleLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
- // Separate the ripple color and alpha channel. The alpha will be
- // applied when we merge the ripples down to the canvas.
- final int rippleARGB;
- if (mState.mColor != null) {
- rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
- } else {
- rippleARGB = Color.TRANSPARENT;
- }
-
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- final int rippleAlpha = Color.alpha(rippleARGB);
- final Paint ripplePaint = mRipplePaint;
- ripplePaint.setColor(rippleARGB);
- ripplePaint.setAlpha(0xFF);
-
boolean drewRipples = false;
int restoreToCount = -1;
int restoreTranslate = -1;
@@ -807,16 +756,21 @@
// first. This will merge SRC_OVER (directly) onto the canvas.
if (restoreToCount < 0) {
final Paint maskingPaint = getMaskingPaint(mode);
- maskingPaint.setAlpha(rippleAlpha);
+ final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
+ final int alpha = Color.alpha(color);
+ maskingPaint.setAlpha(alpha / 2);
+
+ // TODO: We can avoid saveLayer here if we're only drawing one
+ // ripple and we don't have content or a translucent mask.
restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
bounds.right, bounds.bottom, maskingPaint);
- restoreTranslate = canvas.save();
// Translate the canvas to the current hotspot bounds.
+ restoreTranslate = canvas.save();
canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
}
- drewRipples |= ripple.draw(canvas, ripplePaint);
+ drewRipples |= ripple.draw(canvas, getRipplePaint());
}
// Always restore the translation.
@@ -845,6 +799,14 @@
return restoreToCount;
}
+ private Paint getRipplePaint() {
+ if (mRipplePaint == null) {
+ mRipplePaint = new Paint();
+ mRipplePaint.setAntiAlias(true);
+ }
+ return mRipplePaint;
+ }
+
private Paint getMaskingPaint(PorterDuffXfermode xfermode) {
if (mMaskingPaint == null) {
mMaskingPaint = new Paint();
diff --git a/graphics/java/android/graphics/pdf/PdfEditor.java b/graphics/java/android/graphics/pdf/PdfEditor.java
new file mode 100644
index 0000000..9837139
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/PdfEditor.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014 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.pdf;
+
+import android.annotation.NonNull;
+import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import dalvik.system.CloseGuard;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+
+import java.io.IOException;
+
+/**
+ * Class for editing PDF files.
+ *
+ * @hide
+ */
+public final class PdfEditor {
+
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
+ private final long mNativeDocument;
+
+ private int mPageCount;
+
+ private ParcelFileDescriptor mInput;
+
+ /**
+ * Creates a new instance.
+ * <p>
+ * <strong>Note:</strong> The provided file descriptor must be <strong>seekable</strong>,
+ * i.e. its data being randomly accessed, e.g. pointing to a file. After finishing
+ * with this class you must call {@link #close()}.
+ * </p>
+ * <p>
+ * <strong>Note:</strong> This class takes ownership of the passed in file descriptor
+ * and is responsible for closing it when the editor is closed.
+ * </p>
+ *
+ * @param input Seekable file descriptor to read from.
+ *
+ * @see #close()
+ */
+ public PdfEditor(@NonNull ParcelFileDescriptor input) throws IOException {
+ if (input == null) {
+ throw new NullPointerException("input cannot be null");
+ }
+
+ final long size;
+ try {
+ Libcore.os.lseek(input.getFileDescriptor(), 0, OsConstants.SEEK_SET);
+ size = Libcore.os.fstat(input.getFileDescriptor()).st_size;
+ } catch (ErrnoException ee) {
+ throw new IllegalArgumentException("file descriptor not seekable");
+ }
+
+ mInput = input;
+ mNativeDocument = nativeOpen(mInput.getFd(), size);
+ mPageCount = nativeGetPageCount(mNativeDocument);
+ mCloseGuard.open("close");
+ }
+
+ /**
+ * Gets the number of pages in the document.
+ *
+ * @return The page count.
+ */
+ public int getPageCount() {
+ throwIfClosed();
+ return mPageCount;
+ }
+
+ /**
+ * Removes the page with a given index.
+ *
+ * @param pageIndex The page to remove.
+ */
+ public void removePage(int pageIndex) {
+ throwIfClosed();
+ throwIfPageNotInDocument(pageIndex);
+ mPageCount = nativeRemovePage(mNativeDocument, pageIndex);
+ }
+
+ /**
+ * Writes the PDF file to the provided destination.
+ * <p>
+ * <strong>Note:</strong> This method takes ownership of the passed in file
+ * descriptor and is responsible for closing it when writing completes.
+ * </p>
+ * @param output The destination.
+ */
+ public void write(ParcelFileDescriptor output) throws IOException {
+ try {
+ throwIfClosed();
+ nativeWrite(mNativeDocument, output.getFd());
+ } finally {
+ IoUtils.closeQuietly(output);
+ }
+ }
+
+ /**
+ * Closes this editor. You should not use this instance
+ * after this method is called.
+ */
+ public void close() {
+ throwIfClosed();
+ doClose();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ if (mInput != null) {
+ doClose();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void doClose() {
+ nativeClose(mNativeDocument);
+ IoUtils.closeQuietly(mInput);
+ mInput = null;
+ mCloseGuard.close();
+ }
+
+ private void throwIfClosed() {
+ if (mInput == null) {
+ throw new IllegalStateException("Already closed");
+ }
+ }
+
+ private void throwIfPageNotInDocument(int pageIndex) {
+ if (pageIndex < 0 || pageIndex >= mPageCount) {
+ throw new IllegalArgumentException("Invalid page index");
+ }
+ }
+
+ private static native long nativeOpen(int fd, long size);
+ private static native void nativeClose(long documentPtr);
+ private static native int nativeGetPageCount(long documentPtr);
+ private static native int nativeRemovePage(long documentPtr, int pageIndex);
+ private static native void nativeWrite(long documentPtr, int fd);
+}
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 1072b3c..359c294 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -239,7 +239,7 @@
}
private void throwIfPageNotInDocument(int pageIndex) {
- if (pageIndex >= mPageCount) {
+ if (pageIndex < 0 || pageIndex >= mPageCount) {
throw new IllegalArgumentException("Invalid page index");
}
}
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index 60fd7f7..a93891a 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -15,6 +15,8 @@
*/
package android.security;
+import android.content.pm.ParceledListSlice;
+
/**
* Caller is required to ensure that {@link KeyStore#unlock
* KeyStore.unlock} was successful.
@@ -32,6 +34,11 @@
// APIs used by Settings
boolean deleteCaCertificate(String alias);
boolean reset();
+ ParceledListSlice getUserCaAliases();
+ ParceledListSlice getSystemCaAliases();
+ boolean containsCaAlias(String alias);
+ byte[] getEncodedCaCertificate(String alias, boolean includeDeletedSystem);
+ List<String> getCaCertificateChainAliases(String rootAlias, boolean includeDeletedSystem);
// APIs used by KeyChainActivity
void setGrant(int uid, String alias, boolean value);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 0da2b99..131e689 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -397,7 +397,8 @@
return KeyStore.getInstance().isHardwareBacked(algorithm);
}
- private static X509Certificate toCertificate(byte[] bytes) {
+ /** @hide */
+ public static X509Certificate toCertificate(byte[] bytes) {
if (bytes == null) {
throw new IllegalArgumentException("bytes == null");
}
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index d7d9743..a20bdae 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -17,7 +17,6 @@
#include "Animator.h"
#include "RenderNode.h"
-#include "TreeInfo.h"
#include "renderthread/TimeLord.h"
namespace android {
@@ -31,11 +30,14 @@
}
AnimationContext::~AnimationContext() {
- startFrame();
+}
+
+void AnimationContext::destroy() {
+ startFrame(TreeInfo::MODE_RT_ONLY);
while (mCurrentFrameAnimations.mNextHandle) {
AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
AnimatorManager& animators = current->mRenderNode->animators();
- animators.endAllAnimators();
+ animators.endAllActiveAnimators();
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle == current,
"endAllAnimators failed to remove from current frame list!");
}
@@ -52,7 +54,7 @@
handle->insertAfter(&mNextFrameAnimations);
}
-void AnimationContext::startFrame() {
+void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
"Missed running animations last frame!");
AnimationHandle* head = mNextFrameAnimations.mNextHandle;
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
index 900d953..909ed36 100644
--- a/libs/hwui/AnimationContext.h
+++ b/libs/hwui/AnimationContext.h
@@ -20,6 +20,7 @@
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
+#include "TreeInfo.h"
#include "renderthread/TimeLord.h"
#include "utils/Macros.h"
@@ -30,7 +31,6 @@
class AnimationListener;
class BaseRenderNodeAnimator;
class RenderNode;
-class TreeInfo;
/*
* AnimationHandle is several classes merged into one.
@@ -90,7 +90,7 @@
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
- ANDROID_API virtual void startFrame();
+ ANDROID_API virtual void startFrame(TreeInfo::TraversalMode mode);
// Runs any animations still left in mCurrentFrameAnimations that were not run
// as part of the standard RenderNode:prepareTree pass.
@@ -98,6 +98,8 @@
ANDROID_API virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener);
+ ANDROID_API virtual void destroy();
+
private:
friend class AnimationHandle;
void addAnimationHandle(AnimationHandle* handle);
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index da65f38..4f3a573 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -161,6 +161,13 @@
return false;
}
+void BaseRenderNodeAnimator::forceEndNow(AnimationContext& context) {
+ if (mPlayState < FINISHED) {
+ mPlayState = FINISHED;
+ callOnFinishedListener(context);
+ }
+}
+
void BaseRenderNodeAnimator::callOnFinishedListener(AnimationContext& context) {
if (mListener.get()) {
context.callOnFinished(this, mListener.get());
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index c52a93f..35a4a09 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -53,6 +53,10 @@
mListener = listener;
}
AnimationListener* listener() { return mListener.get(); }
+ ANDROID_API void setAllowRunningAsync(bool mayRunAsync) {
+ mMayRunAsync = mayRunAsync;
+ }
+ bool mayRunAsync() { return mMayRunAsync; }
ANDROID_API void start() { mStagingPlayState = RUNNING; onStagingPlayStateChanged(); }
ANDROID_API void end() { mStagingPlayState = FINISHED; onStagingPlayStateChanged(); }
@@ -68,6 +72,8 @@
ANDROID_API virtual uint32_t dirtyMask() = 0;
+ void forceEndNow(AnimationContext& context);
+
protected:
BaseRenderNodeAnimator(float finalValue);
virtual ~BaseRenderNodeAnimator();
@@ -99,6 +105,7 @@
nsecs_t mStartTime;
nsecs_t mDuration;
nsecs_t mStartDelay;
+ bool mMayRunAsync;
sp<AnimationListener> mListener;
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 678b1ee..c28fb88 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -49,6 +49,9 @@
void AnimatorManager::setAnimationHandle(AnimationHandle* handle) {
LOG_ALWAYS_FATAL_IF(mAnimationHandle && handle, "Already have an AnimationHandle!");
mAnimationHandle = handle;
+ LOG_ALWAYS_FATAL_IF(!mAnimationHandle && mAnimators.size(),
+ "Lost animation handle on %p (%s) with outstanding animators!",
+ &mParent, mParent.getName());
}
template<typename T>
@@ -62,6 +65,9 @@
void AnimatorManager::pushStaging() {
if (mNewAnimators.size()) {
+ LOG_ALWAYS_FATAL_IF(!mAnimationHandle,
+ "Trying to start new animators on %p (%s) without an animation handle!",
+ &mParent, mParent.getName());
// Since this is a straight move, we don't need to inc/dec the ref count
move_all(mNewAnimators, mAnimators);
}
@@ -84,6 +90,9 @@
if (animator->isRunning()) {
mInfo.out.hasAnimations = true;
}
+ if (CC_UNLIKELY(!animator->mayRunAsync())) {
+ mInfo.out.requiresUiRedraw = true;
+ }
}
return remove;
}
@@ -128,22 +137,7 @@
return functor.dirtyMask;
}
-class EndAnimatorsFunctor {
-public:
- EndAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
-
- void operator() (BaseRenderNodeAnimator* animator) {
- animator->end();
- animator->pushStaging(mContext);
- animator->animate(mContext);
- animator->decStrong(0);
- }
-
-private:
- AnimationContext& mContext;
-};
-
-static void endAnimatorsHard(BaseRenderNodeAnimator* animator) {
+static void endStagingAnimator(BaseRenderNodeAnimator* animator) {
animator->end();
if (animator->listener()) {
animator->listener()->onAnimationFinished(animator);
@@ -151,24 +145,34 @@
animator->decStrong(0);
}
-void AnimatorManager::endAllAnimators() {
- if (mNewAnimators.size()) {
- // Since this is a straight move, we don't need to inc/dec the ref count
- move_all(mNewAnimators, mAnimators);
+void AnimatorManager::endAllStagingAnimators() {
+ ALOGD("endAllStagingAnimators on %p (%s)", &mParent, mParent.getName());
+ // This works because this state can only happen on the UI thread,
+ // which means we're already on the right thread to invoke listeners
+ for_each(mNewAnimators.begin(), mNewAnimators.end(), endStagingAnimator);
+ mNewAnimators.clear();
+}
+
+class EndActiveAnimatorsFunctor {
+public:
+ EndActiveAnimatorsFunctor(AnimationContext& context) : mContext(context) {}
+
+ void operator() (BaseRenderNodeAnimator* animator) {
+ animator->forceEndNow(mContext);
+ animator->decStrong(0);
}
- // First try gracefully ending them
- if (mAnimationHandle) {
- EndAnimatorsFunctor functor(mAnimationHandle->context());
- for_each(mAnimators.begin(), mAnimators.end(), functor);
- mAnimators.clear();
- mAnimationHandle->release();
- } else {
- // We have no context, so bust out the sledgehammer
- // This works because this state can only happen on the UI thread,
- // which means we're already on the right thread to invoke listeners
- for_each(mAnimators.begin(), mAnimators.end(), endAnimatorsHard);
- mAnimators.clear();
- }
+
+private:
+ AnimationContext& mContext;
+};
+
+void AnimatorManager::endAllActiveAnimators() {
+ ALOGD("endAllStagingAnimators on %p (%s) with handle %p",
+ &mParent, mParent.getName(), mAnimationHandle);
+ EndActiveAnimatorsFunctor functor(mAnimationHandle->context());
+ for_each(mAnimators.begin(), mAnimators.end(), functor);
+ mAnimators.clear();
+ mAnimationHandle->release();
}
} /* namespace uirenderer */
diff --git a/libs/hwui/AnimatorManager.h b/libs/hwui/AnimatorManager.h
index d5f56ed..d03d427 100644
--- a/libs/hwui/AnimatorManager.h
+++ b/libs/hwui/AnimatorManager.h
@@ -50,8 +50,12 @@
void animateNoDamage(TreeInfo& info);
- // Hard-ends all animators. Used for cleanup if the root is being destroyed.
- ANDROID_API void endAllAnimators();
+ // Hard-ends all animators. May only be called on the UI thread.
+ ANDROID_API void endAllStagingAnimators();
+
+ // Hard-ends all animators that have been pushed. Used for cleanup if
+ // the ActivityContext is being destroyed
+ void endAllActiveAnimators();
bool hasAnimators() { return mAnimators.size(); }
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 9855f71..f853d1f 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -551,9 +551,13 @@
}
void Caches::bindTexture(GLenum target, GLuint texture) {
- if (mBoundTextures[mTextureUnit] != texture) {
+ if (target == GL_TEXTURE_2D) {
+ bindTexture(texture);
+ } else {
+ // GLConsumer directly calls glBindTexture() with
+ // target=GL_TEXTURE_EXTERNAL_OES, don't cache this target
+ // since the cached state could be stale
glBindTexture(target, texture);
- mBoundTextures[mTextureUnit] = texture;
}
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 726b74d..7aa628c 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -431,6 +431,7 @@
uint32_t mFunctorsCount;
+ // Caches texture bindings for the GL_TEXTURE_2D target
GLuint mBoundTextures[REQUIRED_TEXTURE_UNITS_COUNT];
OverdrawColorSet mOverdrawDebugColorSet;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index e6bc4db..91c4aee 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -29,15 +29,15 @@
namespace android {
namespace uirenderer {
-Layer::Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
+Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
: caches(Caches::getInstance())
, renderState(renderState)
- , texture(caches) {
+ , texture(caches)
+ , type(layerType) {
mesh = NULL;
meshElementCount = 0;
cacheable = true;
dirty = false;
- textureLayer = false;
renderTarget = GL_TEXTURE_2D;
texture.width = layerWidth;
texture.height = layerHeight;
@@ -54,11 +54,18 @@
convexMask = NULL;
caches.resourceCache.incrementRefcount(this);
rendererLightPosDirty = true;
- renderState.registerLayer(this);
+ wasBuildLayered = false;
+ if (!isTextureLayer()) {
+ // track only non-texture layer lifecycles in renderstate,
+ // because texture layers are destroyed via finalizer
+ renderState.registerLayer(this);
+ }
}
Layer::~Layer() {
- renderState.unregisterLayer(this);
+ if (!isTextureLayer()) {
+ renderState.unregisterLayer(this);
+ }
SkSafeUnref(colorFilter);
removeFbo();
deleteTexture();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 38c29c7..36a4ed1 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -54,7 +54,12 @@
*/
class Layer {
public:
- Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
+ enum Type {
+ kType_Texture,
+ kType_DisplayList,
+ };
+
+ Layer(Type type, RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
~Layer();
static uint32_t computeIdealWidth(uint32_t layerWidth);
@@ -219,11 +224,7 @@
}
inline bool isTextureLayer() const {
- return textureLayer;
- }
-
- inline void setTextureLayer(bool textureLayer) {
- this->textureLayer = textureLayer;
+ return type == kType_Texture;
}
inline SkColorFilter* getColorFilter() const {
@@ -306,6 +307,7 @@
Rect dirtyRect;
bool debugDrawUpdate;
bool hasDrawnSinceUpdate;
+ bool wasBuildLayered;
private:
void requireRenderer();
@@ -342,10 +344,9 @@
bool cacheable;
/**
- * When set to true, this layer must be treated as a texture
- * layer.
+ * Denotes whether the layer is a DisplayList, or Texture layer.
*/
- bool textureLayer;
+ const Type type;
/**
* When set to true, this layer is dirty and should be cleared
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index efa30ac..d49daf6 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -112,7 +112,7 @@
} else {
LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
- layer = new Layer(renderState, entry.mWidth, entry.mHeight);
+ layer = new Layer(Layer::kType_DisplayList, renderState, entry.mWidth, entry.mHeight);
layer->setBlend(true);
layer->setEmpty(true);
layer->setFbo(0);
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e3b0daf..103c843 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -272,9 +272,8 @@
Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
LAYER_RENDERER_LOGD("Creating new texture layer");
- Layer* layer = new Layer(renderState, 0, 0);
+ Layer* layer = new Layer(Layer::kType_Texture, renderState, 0, 0);
layer->setCacheable(false);
- layer->setTextureLayer(true);
layer->setEmpty(true);
layer->setFbo(0);
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0f36c06..dbd273d 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -605,6 +605,12 @@
AutoFence fence;
}
+void OpenGLRenderer::markLayersAsBuildLayers() {
+ for (size_t i = 0; i < mLayerUpdates.size(); i++) {
+ mLayerUpdates[i]->wasBuildLayered = true;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e9ca5d9..e295b1a 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -150,6 +150,7 @@
void cancelLayerUpdate(Layer* layer);
void clearLayerUpdates();
void flushLayerUpdates();
+ void markLayersAsBuildLayers();
virtual int saveLayer(float left, float top, float right, float bottom,
const SkPaint* paint, int flags) {
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index e30ac19..281ca02 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -162,14 +162,21 @@
}
/**
- * Outset the bounds of point data (for line endpoints or points) to account for AA stroke
+ * Outset the bounds of point data (for line endpoints or points) to account for stroke
* geometry.
+ *
+ * bounds are in pre-scaled space.
*/
void expandBoundsForStroke(Rect* bounds) const {
- float outset = halfStrokeWidth;
- if (outset == 0) outset = 0.5f;
- bounds->outset(outset * inverseScaleX + Vertex::GeometryFudgeFactor(),
- outset * inverseScaleY + Vertex::GeometryFudgeFactor());
+ if (halfStrokeWidth == 0) {
+ // hairline, outset by (0.5f + fudge factor) in post-scaling space
+ bounds->outset(fabs(inverseScaleX) * (0.5f + Vertex::GeometryFudgeFactor()),
+ fabs(inverseScaleY) * (0.5f + Vertex::GeometryFudgeFactor()));
+ } else {
+ // non hairline, outset by half stroke width pre-scaled, and fudge factor post scaled
+ bounds->outset(halfStrokeWidth + fabs(inverseScaleX) * Vertex::GeometryFudgeFactor(),
+ halfStrokeWidth + fabs(inverseScaleY) * Vertex::GeometryFudgeFactor());
+ }
}
};
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 23fe1b9..a8b8b16 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -328,8 +328,7 @@
"",
// Matrix
" fragColor *= colorMatrix;\n"
- " fragColor += colorMatrixVector;\n"
- " fragColor.rgb *= fragColor.a;\n",
+ " fragColor += colorMatrixVector;\n",
// PorterDuff
" fragColor = blendColors(colorBlend, fragColor);\n"
};
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6a92a6e..254492f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -58,6 +58,19 @@
fflush(file);
}
+void RenderNode::debugDumpLayers(const char* prefix) {
+ if (mLayer) {
+ ALOGD("%sNode %p (%s) has layer %p (fbo = %u, wasBuildLayered = %s)",
+ prefix, this, getName(), mLayer, mLayer->getFbo(),
+ mLayer->wasBuildLayered ? "true" : "false");
+ }
+ if (mDisplayListData) {
+ for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
+ mDisplayListData->children()[i]->mRenderNode->debugDumpLayers(prefix);
+ }
+ }
+}
+
RenderNode::RenderNode()
: mDirtyPropertyFields(0)
, mNeedsDisplayListDataSync(false)
@@ -413,7 +426,7 @@
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
- // TODO: support both reveal clip and outline clip simultaneously
+ // TODO: support nesting round rect clips
if (mProperties.getRevealClip().willClip()) {
Rect bounds;
mProperties.getRevealClip().getBounds(&bounds);
@@ -421,7 +434,6 @@
} else if (mProperties.getOutline().willClip()) {
renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline()));
}
-
}
/**
@@ -860,6 +872,8 @@
handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
renderer.getSaveCount() - 1, properties().getClipToBounds());
} else {
+ const int saveCountOffset = renderer.getSaveCount() - 1;
+ const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
@@ -870,8 +884,6 @@
issueOperationsOf3dChildren(kNegativeZChildren,
initialTransform, zTranslatedNodes, renderer, handler);
- const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index d897997..f329283 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -102,6 +102,7 @@
};
ANDROID_API static void outputLogBuffer(int fd);
+ void debugDumpLayers(const char* prefix);
ANDROID_API void setStagingDisplayList(DisplayListData* newData);
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0c8d07f..46eeb6a 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -569,6 +569,10 @@
return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
}
+ bool hasShadow() const {
+ return getZ() >= 0.0f && getOutline().getPath() != NULL;
+ }
+
private:
// Rendering properties
struct PrimitiveFields {
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index 9948b44..ec8307f 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -15,6 +15,8 @@
*/
#include "RenderState.h"
+#include "renderthread/CanvasContext.h"
+
namespace android {
namespace uirenderer {
@@ -36,8 +38,27 @@
}
void RenderState::onGLContextDestroyed() {
+ AutoMutex _lock(mLayerLock);
if (CC_UNLIKELY(!mActiveLayers.empty())) {
mCaches->dumpMemoryUsage();
+ for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
+ cit != mRegisteredContexts.end(); cit++) {
+ renderthread::CanvasContext* context = *cit;
+ ALOGD("Context: %p (root = %p)", context, context->mRootRenderNode.get());
+ ALOGD(" Prefeteched layers: %zu", context->mPrefetechedLayers.size());
+ for (std::set<RenderNode*>::iterator pit = context->mPrefetechedLayers.begin();
+ pit != context->mPrefetechedLayers.end(); pit++) {
+ (*pit)->debugDumpLayers(" ");
+ }
+ context->mRootRenderNode->debugDumpLayers(" ");
+ }
+
+ for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
+ lit != mActiveLayers.end(); lit++) {
+ const Layer* layer = *(lit);
+ ALOGD("Layer %p, fbo %d, buildlayered %d",
+ layer, layer->getFbo(), layer->wasBuildLayered);
+ }
LOG_ALWAYS_FATAL("layers have survived gl context destruction");
}
}
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index 3915fb5..74bafca 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -19,6 +19,7 @@
#include <set>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <utils/Mutex.h>
#include <private/hwui/DrawGlInfo.h>
@@ -29,6 +30,7 @@
namespace uirenderer {
namespace renderthread {
+class CanvasContext;
class RenderThread;
}
@@ -51,12 +53,22 @@
void debugOverdraw(bool enable, bool clear);
void registerLayer(const Layer* layer) {
+ AutoMutex _lock(mLayerLock);
mActiveLayers.insert(layer);
}
void unregisterLayer(const Layer* layer) {
+ AutoMutex _lock(mLayerLock);
mActiveLayers.erase(layer);
}
+ void registerCanvasContext(renderthread::CanvasContext* context) {
+ mRegisteredContexts.insert(context);
+ }
+
+ void unregisterCanvasContext(renderthread::CanvasContext* context) {
+ mRegisteredContexts.erase(context);
+ }
+
private:
friend class renderthread::RenderThread;
friend class Caches;
@@ -69,10 +81,12 @@
Caches* mCaches;
std::set<const Layer*> mActiveLayers;
+ std::set<renderthread::CanvasContext*> mRegisteredContexts;
GLsizei mViewportWidth;
GLsizei mViewportHeight;
GLuint mFramebuffer;
+ Mutex mLayerLock;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index ecc47d2..cf8229fd 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -216,14 +216,22 @@
// Clipping round rect
///////////////////////////////////////////////////////////////////////////////
-void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius) {
+void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
+ float radius, bool highPriority) {
if (bounds.isEmpty()) {
clipRect->setEmpty();
return;
}
+ if (roundRectClipState && roundRectClipState->highPriority) {
+ // ignore, don't replace, already have a high priority clip
+ return;
+ }
+
RoundRectClipState* state = new (allocator) RoundRectClipState;
+ state->highPriority = highPriority;
+
// store the inverse drawing matrix
Matrix4 roundRectDrawingMatrix;
roundRectDrawingMatrix.load(getOrthoMatrix());
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index ad4ee9d..549de9b 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -55,6 +55,7 @@
|| rect.intersects(dangerRects[3]);
}
+ bool highPriority;
Matrix4 matrix;
Rect dangerRects[4];
Rect innerRect;
@@ -166,8 +167,11 @@
/**
* Sets (and replaces) the current clipping outline
+ *
+ * If the current round rect clip is high priority, the incoming clip is ignored.
*/
- void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius);
+ void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds,
+ float radius, bool highPriority);
/**
* Indicates whether this snapshot should be ignored. A snapshot
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index 3e1aed3..12b8c8d 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -198,13 +198,13 @@
clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op);
}
if (outlineIsRounded) {
- setClippingRoundRect(allocator, bounds, radius);
+ setClippingRoundRect(allocator, bounds, radius, false);
}
}
void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius) {
- mSnapshot->setClippingRoundRect(allocator, rect, radius);
+ const Rect& rect, float radius, bool highPriority) {
+ mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority);
}
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index c6974b4..745e48a 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -97,7 +97,7 @@
*/
void setClippingOutline(LinearAllocator& allocator, const Outline* outline);
void setClippingRoundRect(LinearAllocator& allocator,
- const Rect& rect, float radius);
+ const Rect& rect, float radius, bool highPriority = true);
inline const mat4* currentTransform() const {
return mSnapshot->transform;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 967cb6f..5e6796c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -48,17 +48,20 @@
, mHaveNewSurface(false)
, mRootRenderNode(rootRenderNode) {
mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
+ mRenderThread.renderState().registerCanvasContext(this);
}
CanvasContext::~CanvasContext() {
destroy();
delete mAnimationContext;
+ mRenderThread.renderState().unregisterCanvasContext(this);
}
void CanvasContext::destroy() {
stopDrawing();
freePrefetechedLayers();
destroyHardwareResources();
+ mAnimationContext->destroy();
if (mCanvas) {
delete mCanvas;
mCanvas = 0;
@@ -147,7 +150,7 @@
if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
info.canvasContext = this;
}
- mAnimationContext->startFrame();
+ mAnimationContext->startFrame(info.mode);
mRootRenderNode->prepareTree(info);
mAnimationContext->runRemainingAnimations(info);
@@ -298,6 +301,7 @@
// purposes when the frame is actually drawn
node->setPropertyFieldsDirty(RenderNode::GENERIC);
+ mCanvas->markLayersAsBuildLayers();
mCanvas->flushLayerUpdates();
node->incStrong(0);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 5984fd0..2460f6b8 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -42,6 +42,7 @@
class OpenGLRenderer;
class Rect;
class Layer;
+class RenderState;
namespace renderthread {
@@ -95,6 +96,9 @@
private:
friend class RegisterFrameCallbackTask;
+ // TODO: Replace with something better for layer & other GL object
+ // lifecycle tracking
+ friend class android::uirenderer::RenderState;
void setSurface(ANativeWindow* window);
void swapBuffers();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 0b91e9d..c461f3a 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -40,6 +40,7 @@
namespace renderthread {
+class CanvasContext;
class DispatchFrameCallbacks;
class EglManager;
class RenderProxy;
diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java
index bdd1195..fcf222b 100644
--- a/location/java/android/location/Location.java
+++ b/location/java/android/location/Location.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -771,6 +772,7 @@
* @see #makeComplete
* @hide
*/
+ @SystemApi
public boolean isComplete() {
if (mProvider == null) return false;
if (!mHasAccuracy) return false;
@@ -788,6 +790,7 @@
* @see #isComplete
* @hide
*/
+ @SystemApi
public void makeComplete() {
if (mProvider == null) mProvider = "?";
if (!mHasAccuracy) {
@@ -957,6 +960,7 @@
* @param isFromMockProvider true if this Location came from a mock provider, false otherwise
* @hide
*/
+ @SystemApi
public void setIsFromMockProvider(boolean isFromMockProvider) {
mIsFromMockProvider = isFromMockProvider;
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 082a158..2c805bb 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1109,9 +1109,9 @@
* {@link #requestLocationUpdates(String, long, float, LocationListener)}.
*
* <p>
- * Before API version 20, this method would throw {@link SecurityException}
- * if the location permissions were not sufficient to use the specified
- * provider.
+ * Before API version {@link android.os.Build.VERSION_CODES#L}, this
+ * method would throw {@link SecurityException} if the location permissions
+ * were not sufficient to use the specified provider.
*
* @param provider the name of the provider
* @return true if the provider exists and is enabled
@@ -1119,7 +1119,6 @@
* @throws IllegalArgumentException if provider is null
*/
public boolean isProviderEnabled(String provider) {
- // STOPSHIP: finalize API version number in javadoc
checkProvider(provider);
try {
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index c9162fe..271f2bb 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -16,6 +16,7 @@
package android.location;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
@@ -84,6 +85,7 @@
*
* @hide
*/
+@SystemApi
public final class LocationRequest implements Parcelable {
/**
* Used with {@link #setQuality} to request the most accurate locations available.
@@ -166,6 +168,7 @@
}
/** @hide */
+ @SystemApi
public static LocationRequest createFromDeprecatedProvider(String provider, long minTime,
float minDistance, boolean singleShot) {
if (minTime < 0) minTime = 0;
@@ -191,6 +194,7 @@
}
/** @hide */
+ @SystemApi
public static LocationRequest createFromDeprecatedCriteria(Criteria criteria, long minTime,
float minDistance, boolean singleShot) {
if (minTime < 0) minTime = 0;
@@ -475,6 +479,7 @@
/** @hide */
+ @SystemApi
public LocationRequest setProvider(String provider) {
checkProvider(provider);
mProvider = provider;
@@ -482,11 +487,13 @@
}
/** @hide */
+ @SystemApi
public String getProvider() {
return mProvider;
}
/** @hide */
+ @SystemApi
public LocationRequest setSmallestDisplacement(float meters) {
checkDisplacement(meters);
mSmallestDisplacement = meters;
@@ -494,6 +501,7 @@
}
/** @hide */
+ @SystemApi
public float getSmallestDisplacement() {
return mSmallestDisplacement;
}
@@ -508,11 +516,13 @@
* @param workSource WorkSource defining power blame for this location request.
* @hide
*/
+ @SystemApi
public void setWorkSource(WorkSource workSource) {
mWorkSource = workSource;
}
/** @hide */
+ @SystemApi
public WorkSource getWorkSource() {
return mWorkSource;
}
@@ -531,11 +541,13 @@
* @see android.app.AppOpsManager
* @hide
*/
+ @SystemApi
public void setHideFromAppOps(boolean hideFromAppOps) {
mHideFromAppOps = hideFromAppOps;
}
/** @hide */
+ @SystemApi
public boolean getHideFromAppOps() {
return mHideFromAppOps;
}
diff --git a/location/java/android/location/SettingInjectorService.java b/location/java/android/location/SettingInjectorService.java
index 98c7864..fcd2cde 100644
--- a/location/java/android/location/SettingInjectorService.java
+++ b/location/java/android/location/SettingInjectorService.java
@@ -196,10 +196,7 @@
* @deprecated not called any more
*/
@Deprecated
- protected String onGetSummary() {
- // Do not delete until no callers have @Override annotations for this method
- return null;
- }
+ protected abstract String onGetSummary();
/**
* Returns the {@link android.preference.Preference#isEnabled()} value. Should not perform
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 5a286ee..e0901d0 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -21,15 +21,24 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.location.LocationManager;
+import android.location.INetInitiatedListener;
+import android.telephony.TelephonyManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.PhoneStateListener;
import android.os.Bundle;
+import android.os.RemoteException;
import android.os.UserHandle;
+import android.os.SystemProperties;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.TelephonyProperties;
/**
* A GPS Network-initiated Handler class used by LocationManager.
@@ -45,55 +54,67 @@
// NI verify activity for bringing up UI (not used yet)
public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";
-
+
// string constants for defining data fields in NI Intent
public static final String NI_INTENT_KEY_NOTIF_ID = "notif_id";
public static final String NI_INTENT_KEY_TITLE = "title";
public static final String NI_INTENT_KEY_MESSAGE = "message";
public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";
-
+
// the extra command to send NI response to GpsLocationProvider
public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";
-
+
// the extra command parameter names in the Bundle
public static final String NI_EXTRA_CMD_NOTIF_ID = "notif_id";
public static final String NI_EXTRA_CMD_RESPONSE = "response";
-
+
// these need to match GpsNiType constants in gps_ni.h
public static final int GPS_NI_TYPE_VOICE = 1;
public static final int GPS_NI_TYPE_UMTS_SUPL = 2;
public static final int GPS_NI_TYPE_UMTS_CTRL_PLANE = 3;
-
- // these need to match GpsUserResponseType constants in gps_ni.h
+ public static final int GPS_NI_TYPE_EMERGENCY_SUPL = 4;
+
+ // these need to match GpsUserResponseType constants in gps_ni.h
public static final int GPS_NI_RESPONSE_ACCEPT = 1;
public static final int GPS_NI_RESPONSE_DENY = 2;
- public static final int GPS_NI_RESPONSE_NORESP = 3;
-
+ public static final int GPS_NI_RESPONSE_NORESP = 3;
+ public static final int GPS_NI_RESPONSE_IGNORE = 4;
+
// these need to match GpsNiNotifyFlags constants in gps_ni.h
public static final int GPS_NI_NEED_NOTIFY = 0x0001;
public static final int GPS_NI_NEED_VERIFY = 0x0002;
public static final int GPS_NI_PRIVACY_OVERRIDE = 0x0004;
-
+
// these need to match GpsNiEncodingType in gps_ni.h
public static final int GPS_ENC_NONE = 0;
public static final int GPS_ENC_SUPL_GSM_DEFAULT = 1;
public static final int GPS_ENC_SUPL_UTF8 = 2;
public static final int GPS_ENC_SUPL_UCS2 = 3;
public static final int GPS_ENC_UNKNOWN = -1;
-
+
private final Context mContext;
-
+ private final TelephonyManager mTelephonyManager;
+ private final PhoneStateListener mPhoneStateListener;
+
// parent gps location provider
private final LocationManager mLocationManager;
-
+
// configuration of notificaiton behavior
private boolean mPlaySounds = false;
private boolean mPopupImmediately = true;
-
- // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
+
+ // read the SUPL_ES form gps.conf
+ private volatile boolean mIsSuplEsEnabled;
+
+ // Set to true if the phone is having emergency call.
+ private volatile boolean mIsInEmergency;
+
+ private final INetInitiatedListener mNetInitiatedListener;
+
+ // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
static private boolean mIsHexInput = true;
-
+
public static class GpsNiNotification
{
public int notificationId;
@@ -109,58 +130,95 @@
public int textEncoding;
public Bundle extras;
};
-
+
public static class GpsNiResponse {
/* User reponse, one of the values in GpsUserResponseType */
int userResponse;
/* Optional extra data to pass with the user response */
Bundle extras;
};
-
+
+ private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
+
+ @Override public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
+ String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
+ /*
+ Emergency Mode is when during emergency call or in emergency call back mode.
+ For checking if it is during emergency call:
+ mIsInEmergency records if the phone is in emergency call or not. It will
+ be set to true when the phone is having emergency call, and then will
+ be set to false by mPhoneStateListener when the emergency call ends.
+ For checking if it is in emergency call back mode:
+ Emergency call back mode will be checked by reading system properties
+ when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
+ */
+ mIsInEmergency |= PhoneNumberUtils.isEmergencyNumber(phoneNumber);
+ if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + mIsInEmergency);
+ }
+ }
+ };
+
/**
* The notification that is shown when a network-initiated notification
- * (and verification) event is received.
+ * (and verification) event is received.
* <p>
* This is lazily created, so use {@link #setNINotification()}.
*/
private Notification mNiNotification;
-
- public GpsNetInitiatedHandler(Context context) {
+
+ public GpsNetInitiatedHandler(Context context,
+ INetInitiatedListener netInitiatedListener,
+ boolean isSuplEsEnabled) {
mContext = context;
+
+ if (netInitiatedListener == null) {
+ throw new IllegalArgumentException("netInitiatedListener is null");
+ } else {
+ mNetInitiatedListener = netInitiatedListener;
+ }
+
+ mIsSuplEsEnabled = isSuplEsEnabled;
mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
+ mTelephonyManager =
+ (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
+
+ mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
+ // listening for emergency call ends
+ if (state == TelephonyManager.CALL_STATE_IDLE) {
+ mIsInEmergency = false;
+ }
+ }
+ };
+ mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
+ mContext.registerReceiver(mBroadcastReciever, intentFilter);
}
-
+
+ public void setSuplEsEnablement(boolean isEnabled)
+ {
+ mIsSuplEsEnabled = isEnabled;
+ }
+
// Handles NI events from HAL
public void handleNiNotification(GpsNiNotification notif)
{
- if (DEBUG) Log.d(TAG, "handleNiNotification" + " notificationId: " + notif.notificationId
- + " requestorId: " + notif.requestorId + " text: " + notif.text);
+ if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
+ + " notificationId: " + notif.notificationId
+ + " requestorId: " + notif.requestorId
+ + " text: " + notif.text
+ + " mIsSuplEsEnabled" + mIsSuplEsEnabled);
- // Notify and verify with immediate pop-up
- if (notif.needNotify && notif.needVerify && mPopupImmediately)
- {
- // Popup the dialog box now
- openNiDialog(notif);
- }
-
- // Notify only, or delayed pop-up (change mPopupImmediately to FALSE)
- if (notif.needNotify && !notif.needVerify ||
- notif.needNotify && notif.needVerify && !mPopupImmediately)
- {
- // Show the notification
-
- // if mPopupImmediately == FALSE and needVerify == TRUE, a dialog will be opened
- // when the user opens the notification message
-
- setNiNotification(notif);
- }
-
- // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify; 3. privacy override.
- if ( notif.needNotify && !notif.needVerify ||
- !notif.needNotify && !notif.needVerify ||
- notif.privacyOverride)
- {
- mLocationManager.sendNiResponse(notif.notificationId, GPS_NI_RESPONSE_ACCEPT);
+ if (mIsSuplEsEnabled == false) {
+ handleNi(notif);
+ } else {
+ handleNiInEs(notif);
}
//////////////////////////////////////////////////////////////////////////
@@ -176,6 +234,72 @@
//
}
+ // handle NI form HAL when SUPL_ES is disabled.
+ private void handleNi(GpsNiNotification notif) {
+ if (DEBUG) Log.d(TAG, "in handleNi () :"
+ + " needNotify: " + notif.needNotify
+ + " needVerify: " + notif.needVerify
+ + " privacyOverride: " + notif.privacyOverride
+ + " mPopupImmediately: " + mPopupImmediately);
+
+ // legacy behaviour
+ if (notif.needNotify) {
+ // If NI does not need verify or the dialog is not requested
+ // to pop up immediately, the dialog box will not pop up.
+ if (notif.needVerify && mPopupImmediately) {
+ // Popup the dialog box now
+ openNiDialog(notif);
+ } else {
+ // Show the notification
+ setNiNotification(notif);
+ }
+ }
+ // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify;
+ // 3. privacy override.
+ if (!notif.needVerify || notif.privacyOverride) {
+ try {
+ mNetInitiatedListener.sendNiResponse(notif.notificationId,
+ GPS_NI_RESPONSE_ACCEPT);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in sendNiResponse");
+ }
+ }
+ }
+
+ // handle NI from HAL when the SUPL_ES is enabled
+ private void handleNiInEs(GpsNiNotification notif) {
+
+ if (DEBUG) Log.d(TAG, "in handleNiInEs () :"
+ + " niType: " + notif.niType
+ + " notificationId: " + notif.notificationId);
+
+ // UE is in emergency mode when in emergency call mode or in emergency call back mode
+ boolean isUEInEmergencyMode = mIsInEmergency ||
+ Boolean.parseBoolean(SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
+
+ /*
+ 1. When SUPL ES bit is off and UE is not in emergency mode:
+ Call handleNi() to do legacy behaviour.
+ 2. When SUPL ES bit is on and UE is in emergency mode:
+ Call handleNi() to do acceptance behaviour.
+ 3. When SUPL ES bit is off but UE is in emergency mode:
+ Ignore the emergency SUPL INIT.
+ 4. When SUPL ES bit is on but UE is not in emergency mode:
+ Ignore the emergency SUPL INIT.
+ */
+ boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
+ if (isNiTypeES != isUEInEmergencyMode) {
+ try {
+ mNetInitiatedListener.sendNiResponse(notif.notificationId,
+ GPS_NI_RESPONSE_IGNORE);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in sendNiResponse");
+ }
+ } else {
+ handleNi(notif);
+ }
+ }
+
// Sets the NI notification.
private synchronized void setNiNotification(GpsNiNotification notif) {
NotificationManager notificationManager = (NotificationManager) mContext
@@ -202,7 +326,7 @@
mNiNotification.defaults |= Notification.DEFAULT_SOUND;
} else {
mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
- }
+ }
mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
mNiNotification.tickerText = getNotifTicker(notif, mContext);
@@ -230,7 +354,7 @@
mContext.startActivity(intent);
}
- // Construct the intent for bringing up the dialog activity, which shows the
+ // Construct the intent for bringing up the dialog activity, which shows the
// notification and takes user input
private Intent getDlgIntent(GpsNiNotification notif)
{
@@ -239,7 +363,7 @@
String message = getDialogMessage(notif, mContext);
// directly bring up the NI activity
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class);
// put data in the intent
@@ -409,7 +533,7 @@
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
decodeString(notif.text, mIsHexInput, notif.textEncoding));
return message;
- }
+ }
// change this to configure dialog display (for verification)
static public String getDialogTitle(GpsNiNotification notif, Context context)
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 308f783..d7ede34 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -162,16 +162,13 @@
public final static int FLAG_BEACON = 0x1 << 3;
/**
- * @hide
- * CANDIDATE FOR PUBLIC API
* Flag requesting the use of an output stream supporting hardware A/V synchronization.
*/
- // TODO add in FLAG_ALL_PUBLIC when in public API
public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
FLAG_BEACON | FLAG_HW_AV_SYNC;
- private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED;
+ private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC;
private int mUsage = USAGE_UNKNOWN;
private int mContentType = CONTENT_TYPE_UNKNOWN;
@@ -530,7 +527,6 @@
}
}
- /** @hide */
public static final Parcelable.Creator<AudioAttributes> CREATOR
= new Parcelable.Creator<AudioAttributes>() {
/**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9ee7027..6da3c0b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -36,6 +36,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.ServiceManager;
@@ -243,7 +244,7 @@
* or unplugged.
* An integer value of 1 indicates a plugged-in state, 0 is unplugged.
*/
- public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
+ public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
/**
* Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels
@@ -251,7 +252,7 @@
* The corresponding integer value is only available when the device is plugged in (as expressed
* by {@link #EXTRA_AUDIO_PLUG_STATE}).
*/
- public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+ public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
/**
* Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by
@@ -261,7 +262,7 @@
* {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use
* {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values.
*/
- public static final String EXTRA_ENCODINGS = "android.media.extra.encodings";
+ public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
/**
* Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
@@ -1959,7 +1960,42 @@
return;
}
- if (!querySoundEffectsEnabled()) {
+ if (!querySoundEffectsEnabled(Process.myUserHandle().getIdentifier())) {
+ return;
+ }
+
+ IAudioService service = getService();
+ try {
+ service.playSoundEffect(effectType);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in playSoundEffect"+e);
+ }
+ }
+
+ /**
+ * Plays a sound effect (Key clicks, lid open/close...)
+ * @param effectType The type of sound effect. One of
+ * {@link #FX_KEY_CLICK},
+ * {@link #FX_FOCUS_NAVIGATION_UP},
+ * {@link #FX_FOCUS_NAVIGATION_DOWN},
+ * {@link #FX_FOCUS_NAVIGATION_LEFT},
+ * {@link #FX_FOCUS_NAVIGATION_RIGHT},
+ * {@link #FX_KEYPRESS_STANDARD},
+ * {@link #FX_KEYPRESS_SPACEBAR},
+ * {@link #FX_KEYPRESS_DELETE},
+ * {@link #FX_KEYPRESS_RETURN},
+ * {@link #FX_KEYPRESS_INVALID},
+ * @param userId The current user to pull sound settings from
+ * NOTE: This version uses the UI settings to determine
+ * whether sounds are heard or not.
+ * @hide
+ */
+ public void playSoundEffect(int effectType, int userId) {
+ if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
+ return;
+ }
+
+ if (!querySoundEffectsEnabled(userId)) {
return;
}
@@ -2006,8 +2042,9 @@
/**
* Settings has an in memory cache, so this is fast.
*/
- private boolean querySoundEffectsEnabled() {
- return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0;
+ private boolean querySoundEffectsEnabled(int user) {
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0;
}
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index 6f1bdef..7c0d758 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -26,6 +26,10 @@
*/
public abstract class AudioManagerInternal {
+ public abstract void adjustSuggestedStreamVolumeForUid(int streamType, int direction,
+ int flags,
+ String callingPackage, int uid);
+
public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid);
diff --git a/media/java/android/media/AudioPortEventHandler.java b/media/java/android/media/AudioPortEventHandler.java
index 8d2c172..9db4994 100644
--- a/media/java/android/media/AudioPortEventHandler.java
+++ b/media/java/android/media/AudioPortEventHandler.java
@@ -47,10 +47,7 @@
mListeners = new ArrayList<AudioManager.OnAudioPortUpdateListener>();
// find the looper for our new event handler
- Looper looper = Looper.myLooper();
- if (looper == null) {
- looper = Looper.getMainLooper();
- }
+ Looper looper = Looper.getMainLooper();
if (looper != null) {
mHandler = new Handler(looper) {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index dd14c11..cd4f31e 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -545,7 +545,7 @@
"ro.config.vc_call_vol_steps",
MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = SystemProperties.getInt(
- "ro.config.music_vol_steps",
+ "ro.config.media_vol_steps",
MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]);
sSoundEffectVolumeDb = context.getResources().getInteger(
@@ -904,6 +904,12 @@
/** @see AudioManager#adjustVolume(int, int) */
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage) {
+ adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
+ Binder.getCallingUid());
+ }
+
+ private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
+ String callingPackage, int uid) {
if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType
+ ", flags=" + flags);
int streamType;
@@ -928,7 +934,7 @@
if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
}
- adjustStreamVolume(streamType, direction, flags, callingPackage);
+ adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
}
/** @see AudioManager#adjustStreamVolume(int, int, int) */
@@ -1777,6 +1783,15 @@
return;
}
+ if ( (mode == AudioSystem.MODE_IN_CALL) &&
+ (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_PHONE_STATE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
return;
}
@@ -1798,7 +1813,7 @@
// must be called synchronized on mSetModeDeathHandlers
// setModeInt() returns a valid PID if the audio mode was successfully set to
// any mode other than NORMAL.
- int setModeInt(int mode, IBinder cb, int pid) {
+ private int setModeInt(int mode, IBinder cb, int pid) {
if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); }
int newModeOwnerPid = 0;
if (cb == null) {
@@ -3058,7 +3073,7 @@
}
boolean checkAudioSettingsPermission(String method) {
- if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS")
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
@@ -5339,6 +5354,15 @@
* LocalServices.
*/
final class AudioServiceInternal extends AudioManagerInternal {
+
+ @Override
+ public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
+ String callingPackage, int uid) {
+ // direction and stream type swap here because the public
+ // adjustSuggested has a different order than the other methods.
+ adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid);
+ }
+
@Override
public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid) {
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 3e8ee93..81ebb14 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -737,6 +737,13 @@
public static final int ERROR_RESOURCE_BUSY = 3;
/**
+ * This indicates that the output protection levels supported by the
+ * device are not sufficient to meet the requirements set by the
+ * content owner in the license policy.
+ */
+ public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+
+ /**
* Retrieve the error code associated with a CryptoException
*/
public int getErrorCode() {
@@ -1622,8 +1629,7 @@
* @throws IllegalStateException if in the Uninitialized state.
*/
public MediaCodecInfo getCodecInfo() {
- return MediaCodecList.getCodecInfoAt(
- MediaCodecList.findCodecByName(getName()));
+ return MediaCodecList.getInfoFor(getName());
}
private native final ByteBuffer[] getBuffers(boolean input);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 323a3e3..01f8193 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -321,6 +321,9 @@
// check feature support
for (Feature feat: getValidFeatures()) {
Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
+ if (yesNo == null) {
+ continue;
+ }
if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
(yesNo == 0 && isFeatureRequired(feat.mName))) {
return false;
@@ -414,7 +417,7 @@
* profile} and {@code level}. If the type, or profile-level combination
* is not understood by the framework, it returns null.
*/
- public static CodecCapabilities CreateFromProfileLevel(
+ public static CodecCapabilities createFromProfileLevel(
String mime, int profile, int level) {
CodecProfileLevel pl = new CodecProfileLevel();
pl.profile = profile;
@@ -470,13 +473,12 @@
Integer yesNo = (Integer)map.get(key);
if (yesNo == null) {
continue;
- } else if (yesNo > 0) {
- mFlagsRequired |= feat.mValue;
- mDefaultFormat.setInteger(key, 1);
- } else {
- mFlagsSupported |= feat.mValue;
- mDefaultFormat.setInteger(key, 1);
}
+ if (yesNo > 0) {
+ mFlagsRequired |= feat.mValue;
+ }
+ mFlagsSupported |= feat.mValue;
+ mDefaultFormat.setInteger(key, 1);
// TODO restrict features by mFlagsVerified once all codecs reliably verify them
}
}
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 5084c5c..0dcbd65 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -116,6 +116,12 @@
/* package private */ static native final int findCodecByName(String codec);
+ /** @hide */
+ public static MediaCodecInfo getInfoFor(String codec) {
+ initCodecList();
+ return sAllCodecInfos[findCodecByName(codec)];
+ }
+
private static native final void native_init();
/**
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 6a4bf07..958ffab 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -2131,7 +2131,7 @@
if (mVolume != volume) {
mVolume = volume;
if (mSvp != null) {
- mSvp.notifyVolumeChanged();
+ mSvp.setCurrentVolume(mVolume);
}
dispatchRouteVolumeChanged(this);
if (mGroup != null) {
@@ -2217,7 +2217,7 @@
// Only register a new listener if necessary
if (mSvp == null || mSvp.getVolumeControl() != volumeControl
|| mSvp.getMaxVolume() != mVolumeMax) {
- mSvp = new SessionVolumeProvider(volumeControl, mVolumeMax);
+ mSvp = new SessionVolumeProvider(volumeControl, mVolumeMax, mVolume);
session.setPlaybackToRemote(mSvp);
}
} else {
@@ -2231,13 +2231,8 @@
class SessionVolumeProvider extends VolumeProvider {
- public SessionVolumeProvider(int volumeControl, int maxVolume) {
- super(volumeControl, maxVolume);
- }
-
- @Override
- public int onGetCurrentVolume() {
- return mVcb == null ? 0 : mVcb.route.mVolume;
+ public SessionVolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+ super(volumeControl, maxVolume, currentVolume);
}
@Override
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index f378cef..d84cf30 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -789,8 +789,12 @@
void startListeningToSessions() {
final ComponentName listenerComponent = new ComponentName(mContext,
mOnClientUpdateListener.getClass());
+ Handler handler = null;
+ if (Looper.myLooper() == null) {
+ handler = new Handler(Looper.getMainLooper());
+ }
mSessionManager.addOnActiveSessionsChangedListener(mSessionListener, listenerComponent,
- UserHandle.myUserId(), null);
+ UserHandle.myUserId(), handler);
mSessionListener.onActiveSessionsChanged(mSessionManager
.getActiveSessions(listenerComponent));
if (DEBUG) {
@@ -976,7 +980,7 @@
synchronized (mInfoLock) {
if (controller == null) {
if (mCurrentSession != null) {
- mCurrentSession.removeCallback(mSessionCb);
+ mCurrentSession.unregisterCallback(mSessionCb);
mCurrentSession = null;
sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
0 /* genId */, 1 /* clearing */, null /* obj */, 0 /* delay */);
@@ -985,12 +989,12 @@
|| !controller.getSessionToken()
.equals(mCurrentSession.getSessionToken())) {
if (mCurrentSession != null) {
- mCurrentSession.removeCallback(mSessionCb);
+ mCurrentSession.unregisterCallback(mSessionCb);
}
sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
0 /* genId */, 0 /* clearing */, null /* obj */, 0 /* delay */);
mCurrentSession = controller;
- mCurrentSession.addCallback(mSessionCb, mEventHandler);
+ mCurrentSession.registerCallback(mSessionCb, mEventHandler);
PlaybackState state = controller.getPlaybackState();
sendMsg(mEventHandler, MSG_NEW_PLAYBACK_STATE, SENDMSG_REPLACE,
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 9bda1d4..5d1e004 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -19,7 +19,9 @@
/**
* Handles requests to adjust or set the volume on a session. This is also used
- * to push volume updates back to the session after a request has been handled.
+ * to push volume updates back to the session. The provider must call
+ * {@link #setCurrentVolume(int)} each time the volume being provided changes.
+ * <p>
* You can set a volume provider on a session by calling
* {@link MediaSession#setPlaybackToRemote}.
*/
@@ -46,29 +48,26 @@
private final int mControlType;
private final int mMaxVolume;
+ private int mCurrentVolume;
private Callback mCallback;
/**
* Create a new volume provider for handling volume events. You must specify
- * the type of volume control and the maximum volume that can be used.
+ * the type of volume control, the maximum volume that can be used, and the
+ * current volume on the output.
*
* @param volumeControl The method for controlling volume that is used by
* this provider.
* @param maxVolume The maximum allowed volume.
+ * @param currentVolume The current volume on the output.
*/
- public VolumeProvider(int volumeControl, int maxVolume) {
+ public VolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
mControlType = volumeControl;
mMaxVolume = maxVolume;
+ mCurrentVolume = currentVolume;
}
/**
- * Get the current volume of the remote playback.
- *
- * @return The current volume.
- */
- public abstract int onGetCurrentVolume();
-
- /**
* Get the volume control type that this volume provider uses.
*
* @return The volume control type for this volume provider
@@ -87,9 +86,23 @@
}
/**
- * Notify the system that the volume has been changed.
+ * Gets the current volume. This will be the last value set by
+ * {@link #setCurrentVolume(int)}.
+ *
+ * @return The current volume.
*/
- public final void notifyVolumeChanged() {
+ public final int getCurrentVolume() {
+ return mCurrentVolume;
+ }
+
+ /**
+ * Notify the system that the current volume has been changed. This must be
+ * called every time the volume changes to ensure it is displayed properly.
+ *
+ * @param currentVolume The current volume on the output.
+ */
+ public final void setCurrentVolume(int currentVolume) {
+ mCurrentVolume = currentVolume;
if (mCallback != null) {
mCallback.onVolumeChanged(this);
}
@@ -97,6 +110,8 @@
/**
* Override to handle requests to set the volume of the current output.
+ * After the volume has been modified {@link #setCurrentVolume} must be
+ * called to notify the system.
*
* @param volume The volume to set the output to.
*/
@@ -107,7 +122,9 @@
* Override to handle requests to adjust the volume of the current output.
* Direction will be one of {@link AudioManager#ADJUST_LOWER},
* {@link AudioManager#ADJUST_RAISE}, {@link AudioManager#ADJUST_SAME}.
- *
+ * After the volume has been modified {@link #setCurrentVolume} must be
+ * called to notify the system.
+ *
* @param direction The direction to change the volume in.
*/
public void onAdjustVolume(int direction) {
diff --git a/media/java/android/media/browse/MediaBrowser.aidl b/media/java/android/media/browse/MediaBrowser.aidl
new file mode 100644
index 0000000..782e094
--- /dev/null
+++ b/media/java/android/media/browse/MediaBrowser.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2014, 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.media.browse;
+
+parcelable MediaBrowser.MediaItem;
\ No newline at end of file
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 338c711..34713e7 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -136,7 +136,7 @@
mState = CONNECT_STATE_CONNECTING;
- final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+ final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
intent.setComponent(mServiceComponent);
final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
@@ -544,12 +544,11 @@
/**
* Create a new MediaItem for use in browsing media.
- *
- * @param flags The flags for this item.
* @param description The description of the media, which must include a
* media id.
+ * @param flags The flags for this item.
*/
- public MediaItem(@Flags int flags, @NonNull MediaDescription description) {
+ public MediaItem(@NonNull MediaDescription description, @Flags int flags) {
if (description == null) {
throw new IllegalArgumentException("description cannot be null");
}
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 4d4d646..be86741 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -329,24 +329,24 @@
}
/**
- * Adds a callback to receive updates from the Session. Updates will be
+ * Registers a callback to receive updates from the Session. Updates will be
* posted on the caller's thread.
*
* @param callback The callback object, must not be null.
*/
- public void addCallback(@NonNull Callback callback) {
- addCallback(callback, null);
+ public void registerCallback(@NonNull Callback callback) {
+ registerCallback(callback, null);
}
/**
- * Adds a callback to receive updates from the session. Updates will be
+ * Registers a callback to receive updates from the session. Updates will be
* posted on the specified handler's thread.
*
* @param callback The callback object, must not be null.
* @param handler The handler to post updates on. If null the callers thread
* will be used.
*/
- public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
+ public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
@@ -359,12 +359,12 @@
}
/**
- * Stop receiving updates on the specified callback. If an update has
- * already been posted you may still receive it after calling this method.
+ * Unregisters the specified callback. If an update has already been posted
+ * you may still receive it after calling this method.
*
* @param callback The callback to remove.
*/
- public void removeCallback(@NonNull Callback callback) {
+ public void unregisterCallback(@NonNull Callback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
@@ -495,7 +495,7 @@
/**
* Callback for receiving updates on from the session. A Callback can be
- * registered using {@link #addCallback}
+ * registered using {@link #registerCallback}
*/
public static abstract class Callback {
/**
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 095f885..2c38697 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -191,11 +191,8 @@
return;
}
if (mCallback != null) {
- if (mCallback.mCallback == callback) {
- Log.w(TAG, "Tried to set same callback, ignoring");
- return;
- }
- // We're changing callbacks, clear the session from the old one.
+ // We're updating the callback, clear the session from the old
+ // one.
mCallback.mCallback.mSession = null;
}
if (handler == null) {
@@ -300,7 +297,7 @@
try {
mBinder.setPlaybackToRemote(volumeProvider.getVolumeControl(),
volumeProvider.getMaxVolume());
- mBinder.setCurrentVolume(volumeProvider.onGetCurrentVolume());
+ mBinder.setCurrentVolume(volumeProvider.getCurrentVolume());
} catch (RemoteException e) {
Log.wtf(TAG, "Failure in setPlaybackToRemote.", e);
}
@@ -478,7 +475,7 @@
return;
}
try {
- mBinder.setCurrentVolume(provider.onGetCurrentVolume());
+ mBinder.setCurrentVolume(provider.getCurrentVolume());
} catch (RemoteException e) {
Log.e(TAG, "Error in notifyVolumeChanged", e);
}
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index aa196a9..06e40c5 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -467,10 +467,7 @@
mSessions.remove(mPi);
} else if (mCb == null) {
mCb = new SessionCallback();
- Handler handler = null;
- if (Looper.myLooper() == null) {
- handler = new Handler(Looper.getMainLooper());
- }
+ Handler handler = new Handler(Looper.getMainLooper());
mSession.setCallback(mCb, handler);
}
}
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
index d5bf38c..b4ec2b3 100644
--- a/media/java/android/media/tv/TvContentRating.java
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -44,45 +44,47 @@
* {@literal
* <rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android"
* android:versionCode="1">
- * <!-- TV content rating system for US TV -->
* <rating-system-definition android:name="US_TV"
- * android:title="US-TV"
- * android:description="@string/description_ustv"
- * android:country="US">
+ * android:country="US"
+ * android:description="@string/description_us_tv">
* <sub-rating-definition android:name="US_TV_D"
* android:title="D"
- * android:description="@string/description_ustv_d" />
+ * android:description="@string/description_us_tv_d" />
* <sub-rating-definition android:name="US_TV_L"
* android:title="L"
- * android:description="@string/description_ustv_l" />
+ * android:description="@string/description_us_tv_l" />
* <sub-rating-definition android:name="US_TV_S"
* android:title="S"
- * android:description="@string/description_ustv_s" />
+ * android:description="@string/description_us_tv_s" />
* <sub-rating-definition android:name="US_TV_V"
* android:title="V"
- * android:description="@string/description_ustv_v" />
+ * android:description="@string/description_us_tv_v" />
* <sub-rating-definition android:name="US_TV_FV"
* android:title="FV"
- * android:description="@string/description_ustv_fv" />
+ * android:description="@string/description_us_tv_fv" />
*
* <rating-definition android:name="US_TV_Y"
* android:title="TV-Y"
- * android:description="@string/description_ustv_y"
- * android:ageHint="0" />
+ * android:description="@string/description_us_tv_y"
+ * android:icon="@drawable/icon_us_tv_y"
+ * android:contentAgeHint="0" />
* <rating-definition android:name="US_TV_Y7"
* android:title="TV-Y7"
- * android:description="@string/description_ustv_y7"
- * android:ageHint="7">
+ * android:description="@string/description_us_tv_y7"
+ * android:icon="@drawable/icon_us_tv_y7"
+ * android:contentAgeHint="7">
* <sub-rating android:name="US_TV_FV" />
* </rating-definition>
* <rating-definition android:name="US_TV_G"
* android:title="TV-G"
- * android:description="@string/description_ustv_g"
- * android:ageHint="0" />
+ * android:description="@string/description_us_tv_g"
+ * android:icon="@drawable/icon_us_tv_g"
+ * android:contentAgeHint="0" />
* <rating-definition android:name="US_TV_PG"
* android:title="TV-PG"
- * android:description="@string/description_ustv_pg"
- * android:ageHint="14">
+ * android:description="@string/description_us_tv_pg"
+ * android:icon="@drawable/icon_us_tv_pg"
+ * android:contentAgeHint="14">
* <sub-rating android:name="US_TV_D" />
* <sub-rating android:name="US_TV_L" />
* <sub-rating android:name="US_TV_S" />
@@ -90,8 +92,9 @@
* </rating-definition>
* <rating-definition android:name="US_TV_14"
* android:title="TV-14"
- * android:description="@string/description_ustv_14"
- * android:ageHint="14">
+ * android:description="@string/description_us_tv_14"
+ * android:icon="@drawable/icon_us_tv_14"
+ * android:contentAgeHint="14">
* <sub-rating android:name="US_TV_D" />
* <sub-rating android:name="US_TV_L" />
* <sub-rating android:name="US_TV_S" />
@@ -99,8 +102,9 @@
* </rating-definition>
* <rating-definition android:name="US_TV_MA"
* android:title="TV-MA"
- * android:description="@string/description_ustv_ma"
- * android:ageHint="17">
+ * android:description="@string/description_us_tv_ma"
+ * android:icon="@drawable/icon_us_tv_ma"
+ * android:contentAgeHint="17">
* <sub-rating android:name="US_TV_L" />
* <sub-rating android:name="US_TV_S" />
* <sub-rating android:name="US_TV_V" />
@@ -175,8 +179,12 @@
* <td>TV content rating system for Brazil</td>
* </tr>
* <tr>
- * <td>CA_TV</td>
- * <td>TV content rating system for Canada</td>
+ * <td>CA_TV_CA</td>
+ * <td>TV content rating system for Canada (Canadian)</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC</td>
+ * <td>TV content rating system for Canada (Quebec)</td>
* </tr>
* <tr>
* <td>CH_TV</td>
@@ -239,6 +247,10 @@
* <td>TV content rating system for Iceland</td>
* </tr>
* <tr>
+ * <td>JP_TV</td>
+ * <td>TV content rating system for Japan</td>
+ * </tr>
+ * <tr>
* <td>KR_TV</td>
* <td>TV content rating system for South Korea</td>
* </tr>
@@ -503,42 +515,67 @@
* <td>Content suitable for viewers over the age of 18</td>
* </tr>
* <tr>
- * <td valign="top" rowspan="7">CA_TV</td>
- * <td>CA_TV_EXEMPT</td>
- * <td>Shows which are exempt from ratings (such as news and sports programming) will not
- * display an on-screen rating at all</td>
+ * <td valign="top" rowspan="7">CA_TV_CA</td>
+ * <td>CA_TV_CA_EXEMPT</td>
+ * <td>Exempt from ratings and won't display an on-screen rating</td>
* </tr>
* <tr>
- * <td>CA_TV_C</td>
- * <td>Programming suitable for children ages of 2-7 years. No profanity or sexual content
- * of any level allowed. Contains little violence</td>
+ * <td>CA_TV_CA_C</td>
+ * <td>Suitable for children ages 2-7. May contain mild violence</td>
* </tr>
* <tr>
- * <td>CA_TV_C8</td>
- * <td>Suitable for children ages 8+. Low level violence and fantasy horror is allowed. No
- * foul language is allowed, but occasional "socially offensive and discriminatory" language
- * is allowed if in the context of the story. No sexual content of any level allowed</td>
+ * <td>CA_TV_CA_C8</td>
+ * <td>Suitable for children ages 8 and older. May contain mild violence, fantasy horror,
+ * and socially offensive language</td>
* </tr>
* <tr>
- * <td>CA_TV_G</td>
- * <td>Suitable for general audiences. Programming suitable for the entire family with mild
- * violence, and mild profanity and/or censored language</td>
+ * <td>CA_TV_CA_G</td>
+ * <td>Suitable for the entire family and may contain mild violence, profanity, and censored
+ * language</td>
* </tr>
* <tr>
- * <td>CA_TV_PG</td>
- * <td>Parental guidance. Moderate violence and moderate profanity is allowed, as is brief
- * nudity and sexual references if important to the context of the story</td>
+ * <td>CA_TV_CA_PG</td>
+ * <td>May contain moderate violence, profanity, nudity, and sexual references</td>
* </tr>
* <tr>
- * <td>CA_TV_14</td>
- * <td>Programming intended for viewers ages 14 and older. May contain strong violence and
- * strong profanity, and depictions of sexual activity as long as they are within the
- * context of a story</td>
+ * <td>CA_TV_CA_14</td>
+ * <td>Intended for viewers ages 14 and older. May contain strong violence and profanity,
+ * and depictions of sexual activity</td>
* </tr>
* <tr>
- * <td>CA_TV_18</td>
- * <td>Programming intended for viewers ages 18 and older. May contain explicit violence and
- * sexual activity</td>
+ * <td>CA_TV_CA_18</td>
+ * <td>Intended for viewers ages 18 and older. May contain explicit violence and sexual
+ * activity</td>
+ * </tr>
+ * <tr>
+ * <td valign="top" rowspan="6">CA_TV_QC</td>
+ * <td>CA_TV_QC_E</td>
+ * <td>Exempt from ratings and won't display an on-screen rating</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC_G</td>
+ * <td>Appropriate for all ages and must contain little or no violence and little to no
+ * sexual content</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC_8</td>
+ * <td>Appropriate for children 8 and may contain with little violence, language, and little
+ * to no sexual situations</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC_13</td>
+ * <td>Suitable for children 13 and may contain with moderate violence, language, and some
+ * sexual situations</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC_16</td>
+ * <td>Recommended for children over the age of 16 and may contain with strong violence,
+ * strong language, and strong sexual content</td>
+ * </tr>
+ * <tr>
+ * <td>CA_TV_QC_18</td>
+ * <td>Only to be viewed by adults and may contain extreme violence and graphic sexual
+ * content. It is mostly used for 18+ movies and pornography</td>
* </tr>
* <tr>
* <td valign="top" rowspan="2">CH_TV</td>
@@ -879,6 +916,23 @@
* <td>Programs suitable for ages 18 and older</td>
* </tr>
* <tr>
+ * <td valign="top" rowspan="4">JP_TV</td>
+ * <td>JP_TV_G</td>
+ * <td>General, suitable for all ages</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_PG12</td>
+ * <td>Parental guidance requested for young people under 12 years</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_R15</td>
+ * <td>For persons aged 15 and above only</td>
+ * </tr>
+ * <tr>
+ * <td>JP_TV_R18</td>
+ * <td>For persons aged 18 and above only</td>
+ * </tr>
+ * <tr>
* <td valign="top" rowspan="5">KR_TV</td>
* <td>KR_TV_ALL</td>
* <td>Appropriate for all ages</td>
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 46b8871..704e4a1 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -102,7 +102,7 @@
/**
* The ID of the TV input to provide to the setup activity and settings activity.
*/
- public static final String EXTRA_INPUT_ID = "inputId";
+ public static final String EXTRA_INPUT_ID = "android.media.tv.extra.INPUT_ID";
private static SparseIntArray sHardwareTypeToTvInputType = new SparseIntArray();
@@ -319,9 +319,9 @@
}
/**
- * Returns an intent to start the setup activity for this TV input service.
+ * Returns an intent to start the setup activity for this TV input.
*/
- public Intent getIntentForSetupActivity() {
+ public Intent createSetupIntent() {
if (!TextUtils.isEmpty(mSetupActivity)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(mService.serviceInfo.packageName, mSetupActivity);
@@ -332,9 +332,9 @@
}
/**
- * Returns an intent to start the settings activity for this TV input service.
+ * Returns an intent to start the settings activity for this TV input.
*/
- public Intent getIntentForSettingsActivity() {
+ public Intent createSettingsIntent() {
if (!TextUtils.isEmpty(mSettingsActivity)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(mService.serviceInfo.packageName, mSettingsActivity);
@@ -532,10 +532,6 @@
DELIMITER_INFO_IN_ID, PREFIX_HARDWARE_DEVICE, hardwareInfo.getDeviceId());
}
- /**
- * Used to make this class parcelable.
- * @hide
- */
public static final Parcelable.Creator<TvInputInfo> CREATOR =
new Parcelable.Creator<TvInputInfo>() {
@Override
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index ddc383a..d2deb66 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -75,7 +75,7 @@
* The TV input is connected.
* <p>
* State for {@link #getInputState} and {@link
- * TvInputManager.TvInputListener#onInputStateChanged}.
+ * TvInputManager.TvInputCallback#onInputStateChanged}.
* </p>
*/
public static final int INPUT_STATE_CONNECTED = 0;
@@ -84,7 +84,7 @@
* fully ready.
* <p>
* State for {@link #getInputState} and {@link
- * TvInputManager.TvInputListener#onInputStateChanged}.
+ * TvInputManager.TvInputCallback#onInputStateChanged}.
* </p>
*/
public static final int INPUT_STATE_CONNECTED_STANDBY = 1;
@@ -92,7 +92,7 @@
* The TV input is disconnected.
* <p>
* State for {@link #getInputState} and {@link
- * TvInputManager.TvInputListener#onInputStateChanged}.
+ * TvInputManager.TvInputCallback#onInputStateChanged}.
* </p>
*/
public static final int INPUT_STATE_DISCONNECTED = 2;
@@ -102,14 +102,14 @@
* {@link #isRatingBlocked}.
*/
public static final String ACTION_BLOCKED_RATINGS_CHANGED =
- "android.media.tv.TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED";
+ "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
/**
* Broadcast intent action when the parental controls enabled state changes. For use with the
* {@link #isParentalControlsEnabled}.
*/
public static final String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED =
- "android.media.tv.TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED";
+ "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
/**
* Broadcast intent action used to query available content rating systems.
@@ -143,7 +143,7 @@
* @see TvContentRating
*/
public static final String ACTION_QUERY_CONTENT_RATING_SYSTEMS =
- "android.media.tv.TvInputManager.ACTION_QUERY_CONTENT_RATING_SYSTEMS";
+ "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
/**
* Content rating systems metadata associated with {@link #ACTION_QUERY_CONTENT_RATING_SYSTEMS}.
@@ -153,15 +153,15 @@
* </p>
*/
public static final String META_DATA_CONTENT_RATING_SYSTEMS =
- "android.media.tv.TvInputManager.META_DATA_CONTENT_RATING_SYSTEMS";
+ "android.media.tv.metadata.CONTENT_RATING_SYSTEMS";
private final ITvInputManager mService;
private final Object mLock = new Object();
// @GuardedBy(mLock)
- private final List<TvInputListenerRecord> mTvInputListenerRecordsList =
- new LinkedList<TvInputListenerRecord>();
+ private final List<TvInputCallbackRecord> mCallbackRecords =
+ new LinkedList<TvInputCallbackRecord>();
// A mapping from TV input ID to the state of corresponding input.
// @GuardedBy(mLock)
@@ -177,7 +177,7 @@
private final ITvInputClient mClient;
- private final ITvInputManagerCallback mCallback;
+ private final ITvInputManagerCallback mManagerCallback;
private final int mUserId;
@@ -445,9 +445,9 @@
}
/**
- * Interface used to monitor status of the TV input.
+ * Callback used to monitor status of the TV input.
*/
- public abstract static class TvInputListener {
+ public abstract static class TvInputCallback {
/**
* This is called when the state of a given TV input is changed.
*
@@ -479,24 +479,24 @@
}
}
- private static final class TvInputListenerRecord {
- private final TvInputListener mListener;
+ private static final class TvInputCallbackRecord {
+ private final TvInputCallback mCallback;
private final Handler mHandler;
- public TvInputListenerRecord(TvInputListener listener, Handler handler) {
- mListener = listener;
+ public TvInputCallbackRecord(TvInputCallback callback, Handler handler) {
+ mCallback = callback;
mHandler = handler;
}
- public TvInputListener getListener() {
- return mListener;
+ public TvInputCallback getCallback() {
+ return mCallback;
}
public void postInputStateChanged(final String inputId, final int state) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onInputStateChanged(inputId, state);
+ mCallback.onInputStateChanged(inputId, state);
}
});
}
@@ -505,7 +505,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onInputAdded(inputId);
+ mCallback.onInputAdded(inputId);
}
});
}
@@ -514,7 +514,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onInputRemoved(inputId);
+ mCallback.onInputRemoved(inputId);
}
});
}
@@ -677,12 +677,12 @@
}
}
};
- mCallback = new ITvInputManagerCallback.Stub() {
+ mManagerCallback = new ITvInputManagerCallback.Stub() {
@Override
public void onInputStateChanged(String inputId, int state) {
synchronized (mLock) {
mStateMap.put(inputId, state);
- for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+ for (TvInputCallbackRecord record : mCallbackRecords) {
record.postInputStateChanged(inputId, state);
}
}
@@ -692,7 +692,7 @@
public void onInputAdded(String inputId) {
synchronized (mLock) {
mStateMap.put(inputId, INPUT_STATE_CONNECTED);
- for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+ for (TvInputCallbackRecord record : mCallbackRecords) {
record.postInputAdded(inputId);
}
}
@@ -702,14 +702,14 @@
public void onInputRemoved(String inputId) {
synchronized (mLock) {
mStateMap.remove(inputId);
- for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+ for (TvInputCallbackRecord record : mCallbackRecords) {
record.postInputRemoved(inputId);
}
}
}
};
try {
- mService.registerCallback(mCallback, mUserId);
+ mService.registerCallback(mManagerCallback, mUserId);
} catch (RemoteException e) {
Log.e(TAG, "mService.registerCallback failed: " + e);
}
@@ -771,39 +771,39 @@
}
/**
- * Registers a {@link TvInputListener}.
+ * Registers a {@link TvInputCallback}.
*
- * @param listener A listener used to monitor status of the TV inputs.
+ * @param callback A callback used to monitor status of the TV inputs.
* @param handler A {@link Handler} that the status change will be delivered to.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void registerListener(TvInputListener listener, Handler handler) {
- if (listener == null) {
+ public void registerCallback(TvInputCallback callback, Handler handler) {
+ if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
if (handler == null) {
throw new IllegalArgumentException("handler cannot be null");
}
synchronized (mLock) {
- mTvInputListenerRecordsList.add(new TvInputListenerRecord(listener, handler));
+ mCallbackRecords.add(new TvInputCallbackRecord(callback, handler));
}
}
/**
- * Unregisters the existing {@link TvInputListener}.
+ * Unregisters the existing {@link TvInputCallback}.
*
- * @param listener The existing listener to remove.
+ * @param callback The existing callback to remove.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
*/
- public void unregisterListener(final TvInputListener listener) {
- if (listener == null) {
+ public void unregisterCallback(final TvInputCallback callback) {
+ if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
synchronized (mLock) {
- for (Iterator<TvInputListenerRecord> it = mTvInputListenerRecordsList.iterator();
+ for (Iterator<TvInputCallbackRecord> it = mCallbackRecords.iterator();
it.hasNext(); ) {
- TvInputListenerRecord record = it.next();
- if (record.getListener() == listener) {
+ TvInputCallbackRecord record = it.next();
+ if (record.getCallback() == callback) {
it.remove();
break;
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 72a6f88..317d472 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -389,8 +389,11 @@
}
/**
- * Informs the application that video is available and the playback of the TV stream has
- * been started.
+ * Informs the application that the video is now available for watching. This is primarily
+ * used to signal the application to unblock the screen. The TV input service must call this
+ * method as soon as the content rendered onto its surface gets ready for viewing.
+ *
+ * @see #notifyVideoUnavailable
*/
public void notifyVideoAvailable() {
runOnMainThread(new Runnable() {
@@ -407,16 +410,18 @@
}
/**
- * Informs the application that video is not available, so the TV input cannot continue
- * playing the TV stream.
+ * Informs the application that the video became unavailable for some reason. This is
+ * primarily used to signal the application to block the screen not to show any intermittent
+ * video artifacts.
*
- * @param reason The reason that the TV input stopped the playback:
- * <ul>
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
- * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
- * </ul>
+ * @param reason The reason why the video became unavailable:
+ * <ul>
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNING}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+ * </ul>
+ * @see #notifyVideoAvailable
*/
public void notifyVideoUnavailable(final int reason) {
if (reason < TvInputManager.VIDEO_UNAVAILABLE_REASON_START
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index f4c761e..4171e6d 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -83,7 +83,7 @@
private Rect mOverlayViewFrame;
private final TvInputManager mTvInputManager;
private MySessionCallback mSessionCallback;
- private TvInputListener mListener;
+ private TvInputCallback mCallback;
private OnUnhandledInputEventListener mOnUnhandledInputEventListener;
private boolean mHasStreamVolume;
private float mStreamVolume;
@@ -170,13 +170,13 @@
}
/**
- * Sets a listener for events in this TvView.
+ * Sets the callback to be invoked when an event is dispatched to this TvView.
*
- * @param listener The listener to be called with events. A value of {@code null} removes any
- * existing listener.
+ * @param callback The callback to receive events. A value of {@code null} removes any existing
+ * callbacks.
*/
- public void setTvInputListener(TvInputListener listener) {
- mListener = listener;
+ public void setCallback(TvInputCallback callback) {
+ mCallback = callback;
}
/**
@@ -680,9 +680,9 @@
}
/**
- * Interface used to receive various status updates on the {@link TvView}.
+ * Callback used to receive various status updates on the {@link TvView}.
*/
- public abstract static class TvInputListener {
+ public abstract static class TvInputCallback {
/**
* This is invoked when an error occurred while establishing a connection to the underlying
@@ -863,8 +863,8 @@
}
} else {
mSessionCallback = null;
- if (mListener != null) {
- mListener.onConnectionFailed(mInputId);
+ if (mCallback != null) {
+ mCallback.onConnectionFailed(mInputId);
}
}
}
@@ -878,8 +878,8 @@
mOverlayViewFrame = null;
mSessionCallback = null;
mSession = null;
- if (mListener != null) {
- mListener.onDisconnected(mInputId);
+ if (mCallback != null) {
+ mCallback.onDisconnected(mInputId);
}
}
@@ -891,8 +891,8 @@
if (DEBUG) {
Log.d(TAG, "onChannelChangedByTvInput(" + channelUri + ")");
}
- if (mListener != null) {
- mListener.onChannelRetuned(mInputId, channelUri);
+ if (mCallback != null) {
+ mCallback.onChannelRetuned(mInputId, channelUri);
}
}
@@ -904,8 +904,8 @@
if (DEBUG) {
Log.d(TAG, "onTracksChanged()");
}
- if (mListener != null) {
- mListener.onTracksChanged(mInputId, tracks);
+ if (mCallback != null) {
+ mCallback.onTracksChanged(mInputId, tracks);
}
}
@@ -918,8 +918,8 @@
Log.d(TAG, "onTrackSelected()");
}
// TODO: Update the video size when the type is TYPE_VIDEO.
- if (mListener != null) {
- mListener.onTrackSelected(mInputId, type, trackId);
+ if (mCallback != null) {
+ mCallback.onTrackSelected(mInputId, type, trackId);
}
}
@@ -931,8 +931,8 @@
if (DEBUG) {
Log.d(TAG, "onVideoAvailable()");
}
- if (mListener != null) {
- mListener.onVideoAvailable(mInputId);
+ if (mCallback != null) {
+ mCallback.onVideoAvailable(mInputId);
}
}
@@ -944,8 +944,8 @@
if (DEBUG) {
Log.d(TAG, "onVideoUnavailable(" + reason + ")");
}
- if (mListener != null) {
- mListener.onVideoUnavailable(mInputId, reason);
+ if (mCallback != null) {
+ mCallback.onVideoUnavailable(mInputId, reason);
}
}
@@ -957,8 +957,8 @@
if (DEBUG) {
Log.d(TAG, "onContentAllowed()");
}
- if (mListener != null) {
- mListener.onContentAllowed(mInputId);
+ if (mCallback != null) {
+ mCallback.onContentAllowed(mInputId);
}
}
@@ -970,8 +970,8 @@
if (DEBUG) {
Log.d(TAG, "onContentBlocked()");
}
- if (mListener != null) {
- mListener.onContentBlocked(mInputId, rating);
+ if (mCallback != null) {
+ mCallback.onContentBlocked(mInputId, rating);
}
}
@@ -1000,8 +1000,8 @@
if (DEBUG) {
Log.d(TAG, "onSessionEvent(" + eventType + ")");
}
- if (mListener != null) {
- mListener.onEvent(mInputId, eventType, eventArgs);
+ if (mCallback != null) {
+ mCallback.onEvent(mInputId, eventType, eventArgs);
}
}
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 317cb96..d50be42 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -51,7 +51,7 @@
* </p>
*
* To extend this class, you must declare the service in your manifest file with
- * an intent filter with the {@link #SERVICE_ACTION} action.
+ * an intent filter with the {@link #SERVICE_INTERFACE} action.
*
* For example:
* </p><pre>
@@ -72,7 +72,7 @@
* The {@link Intent} that must be declared as handled by the service.
*/
@SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
+ public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
private final Handler mHandler = new Handler();
@@ -270,7 +270,7 @@
@Override
public IBinder onBind(Intent intent) {
- if (SERVICE_ACTION.equals(intent.getAction())) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
return mBinder;
}
return null;
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f1e1099..1cf589d 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -62,6 +62,7 @@
jint cryptoErrorNoKey;
jint cryptoErrorKeyExpired;
jint cryptoErrorResourceBusy;
+ jint cryptoErrorInsufficientOutputProtection;
} gCryptoErrorCodes;
static struct CodecActionCodes {
@@ -756,6 +757,9 @@
case ERROR_DRM_RESOURCE_BUSY:
err = gCryptoErrorCodes.cryptoErrorResourceBusy;
break;
+ case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+ err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
+ break;
default: /* Other negative DRM error codes go out as is. */
break;
}
@@ -1434,6 +1438,11 @@
gCryptoErrorCodes.cryptoErrorResourceBusy =
env->GetStaticIntField(clazz.get(), field);
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
+ CHECK(field != NULL);
+ gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
+ env->GetStaticIntField(clazz.get(), field);
+
clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
CHECK(clazz.get() != NULL);
field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index b08fdab..36bb72f 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -17,10 +17,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Dokumenty"</string>
- <string name="title_open" msgid="4353228937663917801">"Otevřít z"</string>
+ <string name="title_open" msgid="4353228937663917801">"Otevřít"</string>
<string name="title_save" msgid="2433679664882857999">"Uložit do"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"Vytvořit složku"</string>
- <string name="menu_grid" msgid="6878021334497835259">"Mřížka"</string>
+ <string name="menu_grid" msgid="6878021334497835259">"Mřížkové zobrazení"</string>
<string name="menu_list" msgid="7279285939892417279">"Seznam"</string>
<string name="menu_sort" msgid="7677740407158414452">"Řadit podle"</string>
<string name="menu_search" msgid="3816712084502856974">"Hledat"</string>
@@ -34,7 +34,7 @@
<string name="menu_advanced_show" product="default" msgid="5792182900084144261">"Zobrazit SD kartu"</string>
<string name="menu_advanced_hide" product="nosdcard" msgid="4218809952721972589">"Skrýt interní úložiště"</string>
<string name="menu_advanced_hide" product="default" msgid="4845869969015718848">"Skrýt SD kartu"</string>
- <string name="menu_file_size_show" msgid="3240323619260823076">"Zobr. velikost souboru"</string>
+ <string name="menu_file_size_show" msgid="3240323619260823076">"Zobrazit velikost souboru"</string>
<string name="menu_file_size_hide" msgid="8881975928502581042">"Skrýt velikost souboru"</string>
<string name="mode_selected_count" msgid="459111894725594625">"Vybráno: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="sort_name" msgid="9183560467917256779">"Podle názvu"</string>
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
index 78b5746..a083f89 100644
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
@@ -40,39 +40,19 @@
android:visibility="gone"
androidprv:allCaps="@bool/kg_use_all_caps" />
- <LinearLayout
- android:layout_width="match_parent"
+ <com.android.keyguard.EmergencyButton
+ android:id="@+id/emergency_call_button"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:layout_marginTop="@dimen/eca_overlap"
- style="?android:attr/buttonBarStyle"
- android:orientation="horizontal"
- android:gravity="center"
- android:weightSum="2">
-
- <com.android.keyguard.EmergencyButton
- android:id="@+id/emergency_call_button"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:drawableLeft="@drawable/lockscreen_emergency_button"
- android:text="@string/kg_emergency_call_label"
- style="?android:attr/buttonBarButtonStyle"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
- android:drawablePadding="8dip"
- android:textAllCaps="@bool/kg_use_all_caps" />
-
- <Button android:id="@+id/forgot_password_button"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- style="?android:attr/buttonBarButtonStyle"
- android:textSize="@dimen/kg_status_line_font_size"
- android:textColor="?android:attr/textColorSecondary"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:visibility="gone"
- android:textAllCaps="@bool/kg_use_all_caps" />
- </LinearLayout>
+ android:drawableLeft="@drawable/lockscreen_emergency_button"
+ android:text="@string/kg_emergency_call_label"
+ style="?android:attr/buttonBarButtonStyle"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textSize="@dimen/kg_status_line_font_size"
+ android:textColor="?android:attr/textColorSecondary"
+ android:drawablePadding="8dip"
+ android:textAllCaps="@bool/kg_use_all_caps" />
</com.android.keyguard.EmergencyCarrierArea>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index e4b81db..b763457 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -21,14 +21,14 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="719438068451601849">"விசைப்பாதுகாப்பு"</string>
- <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"SIM PUK மற்றும் புதிய PIN குறியீட்டைத் தட்டச்சு செய்யவும்"</string>
- <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK குறியீடு"</string>
- <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"புதிய SIM PIN குறியீடு"</string>
+ <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"சிம் PUK மற்றும் புதிய பின் குறியீட்டைத் தட்டச்சு செய்யவும்"</string>
+ <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"சிம் PUK குறியீடு"</string>
+ <string name="keyguard_password_enter_pin_prompt" msgid="3201151840570492538">"புதிய சிம் பின் குறியீடு"</string>
<string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"திறக்க, கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, PIN ஐ உள்ளிடவும்"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான PIN குறியீடு."</string>
+ <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"திறக்க, பின்னை உள்ளிடவும்"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"தவறான பின் குறியீடு."</string>
<string name="keyguard_label_text" msgid="861796461028298424">"தடைநீக்க, மெனுவை அழுத்தி பின்பு 0 ஐ அழுத்தவும்."</string>
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"முகம் திறப்பதற்கான அதிகபட்ச முயற்சிகள் கடந்தன"</string>
<string name="keyguard_charged" msgid="3272223906073492454">"சார்ஜ் செய்யப்பட்டது"</string>
@@ -36,16 +36,16 @@
<string name="keyguard_low_battery" msgid="8143808018719173859">"உங்கள் சார்ஜரை இணைக்கவும்."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"திறக்க, மெனுவை அழுத்தவும்."</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"பிணையம் பூட்டப்பட்டது"</string>
- <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"SIM கார்டு இல்லை"</string>
- <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"டேப்லெட்டில் SIM கார்டு இல்லை."</string>
- <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"தொலைபேசியில் SIM கார்டு இல்லை."</string>
- <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"SIM கார்டைச் செருகவும்."</string>
- <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"SIM கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. SIM கார்டைச் செருகவும்."</string>
- <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"SIM கார்டைப் பயன்படுத்த முடியாது."</string>
- <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"உங்கள் SIM கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு SIM கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
- <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM கார்டு பூட்டப்பட்டுள்ளது."</string>
- <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
- <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
+ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"சிம் கார்டு இல்லை"</string>
+ <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"டேப்லெட்டில் சிம் கார்டு இல்லை."</string>
+ <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"தொலைபேசியில் சிம் கார்டு இல்லை."</string>
+ <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"சிம் கார்டைச் செருகவும்."</string>
+ <string name="keyguard_missing_sim_instructions_long" msgid="5968985489463870358">"சிம் கார்டு இல்லை அல்லது படிக்கக்கூடியதாக இல்லை. சிம் கார்டைச் செருகவும்."</string>
+ <string name="keyguard_permanent_disabled_sim_message_short" msgid="8340813989586622356">"சிம் கார்டைப் பயன்படுத்த முடியாது."</string>
+ <string name="keyguard_permanent_disabled_sim_instructions" msgid="5892940909699723544">"உங்கள் சிம் கார்டு நிரந்தரமாக முடக்கப்பட்டது.\n மற்றொரு சிம் கார்டிற்காக உங்கள் வயர்லெஸ் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string>
+ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string>
+ <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"சிம் கார்டு PUK ஆல் பூட்டப்பட்டது."</string>
+ <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
<string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. விட்ஜெட் %2$d / %3$d."</string>
<string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"விட்ஜெட்டைச் சேர்க்கவும்."</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"காலியானது"</string>
@@ -103,20 +103,20 @@
<string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"வடிவத்தை மறந்துவிட்டீர்களா"</string>
<string name="kg_wrong_pattern" msgid="1850806070801358830">"தவறான வடிவம்"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"தவறான கடவுச்சொல்"</string>
- <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான PIN"</string>
+ <string name="kg_wrong_pin" msgid="1131306510833563801">"தவறான பின்"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_pattern_instructions" msgid="398978611683075868">"உங்கள் வடிவத்தை வரையவும்"</string>
- <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"SIM PIN ஐ உள்ளிடவும்"</string>
- <string name="kg_pin_instructions" msgid="2377242233495111557">"PIN ஐ உள்ளிடுக"</string>
+ <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"சிம் பின்னை உள்ளிடவும்"</string>
+ <string name="kg_pin_instructions" msgid="2377242233495111557">"பின்னை உள்ளிடுக"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"கடவுச்சொல்லை உள்ளிடவும்"</string>
- <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
- <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய PIN குறியீட்டை உள்ளிடவும்"</string>
- <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய PIN குறியீட்டை உறுதிப்படுத்தவும்"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM கார்டின் தடையைநீக்குகிறது..."</string>
- <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள PIN ஐ உள்ளிடவும்."</string>
+ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர்வதற்கு PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு மொபைல் நிறுவனங்களைத் தொடர்புகொள்ளவும்."</string>
+ <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"விரும்பிய பின் குறியீட்டை உள்ளிடவும்"</string>
+ <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"விரும்பிய பின் குறியீட்டை உறுதிப்படுத்தவும்"</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"சிம் கார்டின் தடையைநீக்குகிறது..."</string>
+ <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"4 இலிருந்து 8 எண்கள் வரையுள்ள பின்னை உள்ளிடவும்."</string>
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK குறியீட்டில் 8 எண்கள் அல்லது அதற்கு மேல் இருக்க வேண்டும்."</string>
- <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் SIM ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
- <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN குறியீடுகள் பொருந்தவில்லை"</string>
+ <string name="kg_invalid_puk" msgid="3638289409676051243">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம் ஐ நிரந்தரமாக முடக்கிவிடும்."</string>
+ <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"பின் குறியீடுகள் பொருந்தவில்லை"</string>
<string name="kg_login_too_many_attempts" msgid="6486842094005698475">"அதிகமான வடிவ முயற்சிகள்"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"திறக்க, உங்கள் Google கணக்கு மூலம் உள்நுழையவும்."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"பயனர்பெயர் (மின்னஞ்சல்)"</string>
@@ -125,7 +125,7 @@
<string name="kg_login_invalid_input" msgid="5754664119319872197">"தவறான பயனர்பெயர் அல்லது கடவுச்சொல்."</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"உங்கள் பயனர்பெயர் அல்லது கடவுச்சொல்லை மறந்துவிட்டீர்களா?\n"<b>"google.com/accounts/recovery"</b>" ஐப் பார்வையிடவும்."</string>
<string name="kg_login_checking_password" msgid="1052685197710252395">"கணக்கைச் சரிபார்க்கிறது…"</string>
- <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் PIN ஐ <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
+ <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக உள்ளிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். \n\n<xliff:g id="NUMBER_1">%d</xliff:g> வினாடிகளில் மீண்டும் முயற்சிக்கவும்."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"டேப்லெட்டைத் திறக்க <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக முயற்சித்துள்ளீர்கள். இன்னும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, டேப்லெட்டானது ஆரம்பநிலைக்கு மீட்டமைக்கப்பட்டு, எல்லா பயனர் தரவையும் இழப்பீர்கள்."</string>
@@ -136,18 +136,18 @@
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"அகற்று"</string>
- <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"SIM PIN குறியீடு தவறானது, உங்கள் சாதனத்தின் தடையை நீக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
+ <string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தின் தடையை நீக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ள வேண்டும்."</string>
<plurals name="kg_password_wrong_pin_code">
- <item quantity="one" msgid="8134313997799638254">"SIM PIN குறியீடு தவறானது, உங்கள் சாதனத்தைத் திறக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளும் முன், மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
- <item quantity="other" msgid="2215723361575359486">"SIM PIN குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="one" msgid="8134313997799638254">"சிம் பின் குறியீடு தவறானது, உங்கள் சாதனத்தைத் திறக்க, உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளும் முன், மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
+ <item quantity="other" msgid="2215723361575359486">"சிம் பின் குறியீடு தவறானது, மேலும் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
</plurals>
- <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"SIM பயன்பாட்டிற்கு உகந்தது அல்ல. உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
+ <string name="kg_password_wrong_puk_code_dead" msgid="7077536808291316208">"சிம் பயன்பாட்டிற்கு உகந்தது அல்ல. உங்கள் மொபைல் நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
<plurals name="kg_password_wrong_puk_code">
- <item quantity="one" msgid="3256893607561060649">"SIM PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
- <item quantity="other" msgid="5477305226026342036">"SIM PUK குறியீடு தவறானது, SIM நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
+ <item quantity="one" msgid="3256893607561060649">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயர்ச்சிக்கலாம்."</item>
+ <item quantity="other" msgid="5477305226026342036">"சிம் PUK குறியீடு தவறானது, சிம் நிரந்தரமாகப் பயன்படுத்த முடியாமல் போவதற்கு முன், நீங்கள் <xliff:g id="NUMBER">%d</xliff:g> முறை முயற்சிக்கலாம்."</item>
</plurals>
- <string name="kg_password_pin_failed" msgid="6268288093558031564">"SIM PIN செயல்பாடு தோல்வி!"</string>
- <string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK செயல்பாடு தோல்வி!"</string>
+ <string name="kg_password_pin_failed" msgid="6268288093558031564">"சிம் பின் செயல்பாடு தோல்வி!"</string>
+ <string name="kg_password_puk_failed" msgid="2838824369502455984">"சிம் PUK செயல்பாடு தோல்வி!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"குறியீடு ஏற்கப்பட்டது!"</string>
<string name="keyguard_transport_prev_description" msgid="8229108430245669854">"முந்தைய டிராக்கிற்கான பொத்தான்"</string>
<string name="keyguard_transport_next_description" msgid="4299258300283778305">"அடுத்த டிராக்கிற்கான பொத்தான்"</string>
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 73b11f3..e0507a8 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -99,8 +99,7 @@
// TODO: implement a shorter timeout once new PowerManager API is ready.
// should be the equivalent to the old userActivity(EMERGENCY_CALL_TIMEOUT)
mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
- if (TelephonyManager.getDefault().getCallState()
- == TelephonyManager.CALL_STATE_OFFHOOK) {
+ if (mLockPatternUtils.isInCall()) {
mLockPatternUtils.resumeCall();
} else {
final boolean bypassHandler = true;
@@ -115,7 +114,7 @@
private void updateEmergencyCallButton(State simState, int phoneState) {
boolean enabled = false;
- if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
+ if (mLockPatternUtils.isInCall()) {
enabled = true; // always show "return to call" if phone is off-hook
} else if (mLockPatternUtils.isEmergencyCallCapable()) {
boolean simLocked = KeyguardUpdateMonitor.getInstance(mContext).isSimLocked();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 65c4ce2..0e01a27 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -15,38 +15,27 @@
*/
package com.android.keyguard;
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.AccountManagerCallback;
-import android.accounts.AccountManagerFuture;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.widget.Button;
import android.widget.LinearLayout;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
-import java.io.IOException;
import java.util.List;
public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView,
@@ -70,9 +59,7 @@
private CountDownTimer mCountdownTimer = null;
private LockPatternUtils mLockPatternUtils;
private LockPatternView mLockPatternView;
- private Button mForgotPatternButton;
private KeyguardSecurityCallback mCallback;
- private boolean mEnableFallback;
/**
* Keeps track of the last time we poked the wake lock during dispatching of the touch event.
@@ -144,20 +131,8 @@
// vibrate mode will be the same for the life of this screen
mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
- mForgotPatternButton = (Button) findViewById(R.id.forgot_password_button);
- // note: some configurations don't have an emergency call area
- if (mForgotPatternButton != null) {
- mForgotPatternButton.setText(R.string.kg_forgot_pattern_button_text);
- mForgotPatternButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- mCallback.showBackupSecurity();
- }
- });
- }
-
setFocusableInTouchMode(true);
- maybeEnableFallback(mContext);
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
mEcaView = findViewById(R.id.keyguard_selector_fade_container);
View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame);
@@ -169,24 +144,6 @@
mHelpMessage = (KeyguardMessageArea) findViewById(R.id.keyguard_message_area);
}
- private void updateFooter(FooterMode mode) {
- if (mForgotPatternButton == null) return; // no ECA? no footer
-
- switch (mode) {
- case Normal:
- if (DEBUG) Log.d(TAG, "mode normal");
- mForgotPatternButton.setVisibility(View.GONE);
- break;
- case ForgotLockPattern:
- if (DEBUG) Log.d(TAG, "mode ForgotLockPattern");
- mForgotPatternButton.setVisibility(View.VISIBLE);
- break;
- case VerifyUnlocked:
- if (DEBUG) Log.d(TAG, "mode VerifyUnlocked");
- mForgotPatternButton.setVisibility(View.GONE);
- }
- }
-
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean result = super.onTouchEvent(ev);
@@ -217,18 +174,6 @@
} else {
displayDefaultSecurityMessage();
}
-
- // the footer depends on how many total attempts the user has failed
- if (mCallback.isVerifyUnlockOnly()) {
- updateFooter(FooterMode.VerifyUnlocked);
- } else if (mEnableFallback &&
- (mKeyguardUpdateMonitor.getFailedUnlockAttempts()
- >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
- updateFooter(FooterMode.ForgotLockPattern);
- } else {
- updateFooter(FooterMode.Normal);
- }
-
}
private void displayDefaultSecurityMessage() {
@@ -291,68 +236,10 @@
}
}
- private void maybeEnableFallback(Context context) {
- // Ask the account manager if we have an account that can be used as a
- // fallback in case the user forgets his pattern.
- AccountAnalyzer accountAnalyzer = new AccountAnalyzer(AccountManager.get(context));
- accountAnalyzer.start();
- }
-
- private class AccountAnalyzer implements AccountManagerCallback<Bundle> {
- private final AccountManager mAccountManager;
- private final Account[] mAccounts;
- private int mAccountIndex;
-
- private AccountAnalyzer(AccountManager accountManager) {
- mAccountManager = accountManager;
- mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
- new UserHandle(mLockPatternUtils.getCurrentUser()));
- }
-
- private void next() {
- // if we are ready to enable the fallback or if we depleted the list of accounts
- // then finish and get out
- if (mEnableFallback || mAccountIndex >= mAccounts.length) {
- return;
- }
-
- // lookup the confirmCredentials intent for the current account
- mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
- null, new UserHandle(mLockPatternUtils.getCurrentUser()));
- }
-
- public void start() {
- mEnableFallback = false;
- mAccountIndex = 0;
- next();
- }
-
- public void run(AccountManagerFuture<Bundle> future) {
- try {
- Bundle result = future.getResult();
- if (result.getParcelable(AccountManager.KEY_INTENT) != null) {
- mEnableFallback = true;
- }
- } catch (OperationCanceledException e) {
- // just skip the account if we are unable to query it
- } catch (IOException e) {
- // just skip the account if we are unable to query it
- } catch (AuthenticatorException e) {
- // just skip the account if we are unable to query it
- } finally {
- mAccountIndex++;
- next();
- }
- }
- }
-
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
mLockPatternView.clearPattern();
mLockPatternView.setEnabled(false);
final long elapsedRealtime = SystemClock.elapsedRealtime();
- if (mEnableFallback) {
- updateFooter(FooterMode.ForgotLockPattern);
- }
mCountdownTimer = new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) {
@@ -367,12 +254,6 @@
public void onFinish() {
mLockPatternView.setEnabled(true);
displayDefaultSecurityMessage();
- // TODO mUnlockIcon.setVisibility(View.VISIBLE);
- if (mEnableFallback) {
- updateFooter(FooterMode.ForgotLockPattern);
- } else {
- updateFooter(FooterMode.Normal);
- }
}
}.start();
@@ -489,13 +370,6 @@
// Also animate the Emergency call
mAppearAnimationUtils.createAnimation(mEcaView, delay, duration, startTranslationY,
interpolator, null);
-
- // And the forgot pattern button
- if (mForgotPatternButton != null
- && mForgotPatternButton.getVisibility() == View.VISIBLE) {
- mAppearAnimationUtils.createAnimation(mForgotPatternButton, delay, duration,
- startTranslationY, interpolator, null);
- }
}
animator.start();
mLockPatternView.invalidate();
diff --git a/packages/PrintSpooler/Android.mk b/packages/PrintSpooler/Android.mk
index 6e1402c..27d1b23 100644
--- a/packages/PrintSpooler/Android.mk
+++ b/packages/PrintSpooler/Android.mk
@@ -19,10 +19,13 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += src/com/android/printspooler/renderer/IPdfRenderer.aidl
+LOCAL_SRC_FILES += \
+ src/com/android/printspooler/renderer/IPdfRenderer.aidl \
+ src/com/android/printspooler/renderer/IPdfEditor.aidl
LOCAL_PACKAGE_NAME := PrintSpooler
+LOCAL_JNI_SHARED_LIBRARIES := libprintspooler_jni
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v7-recyclerview
include $(BUILD_PACKAGE)
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 9efda2f..adff596 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -54,7 +54,7 @@
</service>
<service
- android:name=".renderer.PdfRendererService"
+ android:name=".renderer.PdfManipulationService"
android:isolatedProcess="true">
</service>
diff --git a/packages/PrintSpooler/jni/Android.mk b/packages/PrintSpooler/jni/Android.mk
index fbf56be..fe7d06b 100644
--- a/packages/PrintSpooler/jni/Android.mk
+++ b/packages/PrintSpooler/jni/Android.mk
@@ -9,9 +9,9 @@
$(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := \
- libnativehelper
-
-LOCAL_LDLIBS := -lm -llog -ljnigraphics
+ libnativehelper \
+ libjnigraphics \
+ liblog
LOCAL_MODULE := libprintspooler_jni
LOCAL_MODULE_TAGS := optional
diff --git a/packages/PrintSpooler/res/layout/preview_page_loading.xml b/packages/PrintSpooler/res/layout/preview_page_loading.xml
new file mode 100644
index 0000000..1af3a17
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/preview_page_loading.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="36dip"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_grayedout_printer"
+ android:contentDescription="@null"
+ android:scaleType="centerInside"
+ android:adjustViewBounds="true">
+ </ImageView>
+
+</FrameLayout>
diff --git a/packages/PrintSpooler/res/values-land/constants.xml b/packages/PrintSpooler/res/values-land/constants.xml
index 6cf9754b5..84fc050 100644
--- a/packages/PrintSpooler/res/values-land/constants.xml
+++ b/packages/PrintSpooler/res/values-land/constants.xml
@@ -16,7 +16,7 @@
<resources>
- <integer name="preview_page_per_row_count">2</integer>
+ <integer name="preview_page_per_row_count">4</integer>
<integer name="print_option_column_count">3</integer>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 5b7fda3..27e1d51 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -76,7 +76,6 @@
<!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
<string name="print_dialog">Print dialog</string>
-
<!-- Template for the message that shows the current page out of the total number of pages -->
<string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
/<xliff:g id="page_count">%2$d</xliff:g></string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index a581e8a..1d8261b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -37,7 +37,7 @@
import android.view.View;
import com.android.internal.annotations.GuardedBy;
import com.android.printspooler.renderer.IPdfRenderer;
-import com.android.printspooler.renderer.PdfRendererService;
+import com.android.printspooler.renderer.PdfManipulationService;
import com.android.printspooler.util.BitmapSerializeUtils;
import dalvik.system.CloseGuard;
import libcore.io.IoUtils;
@@ -490,7 +490,8 @@
new AsyncTask<Void, Void, Integer>() {
@Override
protected void onPreExecute() {
- Intent intent = new Intent(mContext, PdfRendererService.class);
+ Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER);
+ intent.setClass(mContext, PdfManipulationService.class);
mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
}
@@ -555,7 +556,7 @@
callback.run();
}
}
- }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
public void destroy() {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 09e8b39..1e7a011 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -317,6 +317,11 @@
return mState == STATE_FAILED;
}
+ public boolean hasLaidOutPages() {
+ return mDocumentInfo.info != null
+ && mDocumentInfo.info.getPageCount() > 0;
+ }
+
public void clearUpdateError() {
if (!hasUpdateError()) {
throw new IllegalStateException("No update error to clear");
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
new file mode 100644
index 0000000..b450ccb
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfEditor.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 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.printspooler.renderer;
+
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+
+/**
+ * Interface for communication with a remote pdf editor.
+ */
+interface IPdfEditor {
+ int openDocument(in ParcelFileDescriptor source);
+ void removePages(in PageRange[] pages);
+ void write(in ParcelFileDescriptor destination);
+ void closeDocument();
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
index 1fba2b1..8e595d7 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/IPdfRenderer.aidl
@@ -29,5 +29,4 @@
oneway void renderPage(int pageIndex, int bitmapWidth, int bitmapHeight,
in PrintAttributes attributes, in ParcelFileDescriptor destination);
oneway void closeDocument();
- oneway void writePages(in PageRange[] pages);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
similarity index 62%
rename from packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
rename to packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index 4d02c01..62716b2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfRendererService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -23,6 +23,7 @@
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.graphics.pdf.PdfEditor;
import android.graphics.pdf.PdfRenderer;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -32,15 +33,21 @@
import android.print.PrintAttributes.Margins;
import android.util.Log;
import android.view.View;
+import com.android.printspooler.util.PageRangeUtils;
import libcore.io.IoUtils;
import com.android.printspooler.util.BitmapSerializeUtils;
import java.io.IOException;
/**
- * Service for rendering PDF documents in an isolated process.
+ * Service for manipulation of PDF documents in an isolated process.
*/
-public final class PdfRendererService extends Service {
- private static final String LOG_TAG = "PdfRendererService";
+public final class PdfManipulationService extends Service {
+ public static final String ACTION_GET_RENDERER =
+ "com.android.printspooler.renderer.ACTION_GET_RENDERER";
+ public static final String ACTION_GET_EDITOR =
+ "com.android.printspooler.renderer.ACTION_GET_EDITOR";
+
+ private static final String LOG_TAG = "PdfManipulationService";
private static final boolean DEBUG = false;
private static final int MILS_PER_INCH = 1000;
@@ -48,7 +55,18 @@
@Override
public IBinder onBind(Intent intent) {
- return new PdfRendererImpl();
+ String action = intent.getAction();
+ switch (action) {
+ case ACTION_GET_RENDERER: {
+ return new PdfRendererImpl();
+ }
+ case ACTION_GET_EDITOR: {
+ return new PdfEditorImpl();
+ }
+ default: {
+ throw new IllegalArgumentException("Invalid intent action:" + action);
+ }
+ }
}
private final class PdfRendererImpl extends IPdfRenderer.Stub {
@@ -60,15 +78,17 @@
@Override
public int openDocument(ParcelFileDescriptor source) throws RemoteException {
synchronized (mLock) {
- throwIfOpened();
- if (DEBUG) {
- Log.i(LOG_TAG, "openDocument()");
- }
try {
+ throwIfOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "openDocument()");
+ }
mRenderer = new PdfRenderer(source);
return mRenderer.getPageCount();
- } catch (IOException ioe) {
- throw new RemoteException("Cannot open file");
+ } catch (IOException|IllegalStateException e) {
+ IoUtils.closeQuietly(source);
+ Log.e(LOG_TAG, "Cannot open file", e);
+ throw new RemoteException(e.toString());
}
}
}
@@ -108,7 +128,7 @@
}
matrix.postScale(displayScale, displayScale);
- Configuration configuration = PdfRendererService.this.getResources()
+ Configuration configuration = PdfManipulationService.this.getResources()
.getConfiguration();
if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
@@ -147,24 +167,13 @@
synchronized (mLock) {
throwIfNotOpened();
if (DEBUG) {
- Log.i(LOG_TAG, "openDocument()");
+ Log.i(LOG_TAG, "closeDocument()");
}
mRenderer.close();
mRenderer = null;
}
}
- @Override
- public void writePages(PageRange[] pages) {
- synchronized (mLock) {
- throwIfNotOpened();
- if (DEBUG) {
- Log.i(LOG_TAG, "writePages()");
- }
- // TODO: Implement dropping undesired pages.
- }
- }
-
private Bitmap getBitmapForSize(int width, int height) {
if (mBitmap != null) {
if (mBitmap.getWidth() == width && mBitmap.getHeight() == height) {
@@ -191,6 +200,91 @@
}
}
+ private final class PdfEditorImpl extends IPdfEditor.Stub {
+ private final Object mLock = new Object();
+
+ private PdfEditor mEditor;
+
+ @Override
+ public int openDocument(ParcelFileDescriptor source) throws RemoteException {
+ synchronized (mLock) {
+ try {
+ throwIfOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "openDocument()");
+ }
+ mEditor = new PdfEditor(source);
+ return mEditor.getPageCount();
+ } catch (IOException|IllegalStateException e) {
+ IoUtils.closeQuietly(source);
+ Log.e(LOG_TAG, "Cannot open file", e);
+ throw new RemoteException(e.toString());
+ }
+ }
+ }
+
+ @Override
+ public void removePages(PageRange[] ranges) {
+ synchronized (mLock) {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "removePages()");
+ }
+
+ ranges = PageRangeUtils.normalize(ranges);
+
+ final int rangeCount = ranges.length;
+ for (int i = rangeCount - 1; i >= 0; i--) {
+ PageRange range = ranges[i];
+ for (int j = range.getEnd(); j >= range.getStart(); j--) {
+ mEditor.removePage(j);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void write(ParcelFileDescriptor destination) throws RemoteException {
+ synchronized (mLock) {
+ try {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "write()");
+ }
+ mEditor.write(destination);
+ } catch (IOException | IllegalStateException e) {
+ IoUtils.closeQuietly(destination);
+ Log.e(LOG_TAG, "Error writing PDF to file.", e);
+ throw new RemoteException(e.toString());
+ }
+ }
+ }
+
+ @Override
+ public void closeDocument() {
+ synchronized (mLock) {
+ throwIfNotOpened();
+ if (DEBUG) {
+ Log.i(LOG_TAG, "closeDocument()");
+ }
+ mEditor.close();
+ mEditor = null;
+ }
+ }
+
+ private void throwIfOpened() {
+ if (mEditor != null) {
+ throw new IllegalStateException("Already opened");
+ }
+ }
+
+ private void throwIfNotOpened() {
+ if (mEditor == null) {
+ throw new IllegalStateException("Not opened");
+ }
+ }
+ }
+
private static int pointsFromMils(int mils) {
return (int) (((float) mils / MILS_PER_INCH) * POINTS_IN_INCH);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index d949673..ce0b9b6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -17,6 +17,9 @@
package com.android.printspooler.ui;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes.MediaSize;
@@ -26,12 +29,12 @@
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
import android.util.SparseArray;
-import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.View.MeasureSpec;
import android.widget.TextView;
import com.android.printspooler.R;
import com.android.printspooler.model.PageContentRepository;
@@ -48,7 +51,7 @@
* This class represents the adapter for the pages in the print preview list.
*/
public final class PageAdapter extends Adapter implements
- PageContentRepository.OnMalformedPdfFileListener{
+ PageContentRepository.OnMalformedPdfFileListener {
private static final String LOG_TAG = "PageAdapter";
private static final int MAX_PREVIEW_PAGES_BATCH = 50;
@@ -86,6 +89,8 @@
// Pages the user selected in the UI.
private PageRange[] mSelectedPages;
+ private BitmapDrawable mEmptyState;
+
private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
private int mSelectedPageCount;
@@ -257,7 +262,7 @@
}
if (updatePreviewAreaAndPageSize) {
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
}
if (documentChanged) {
@@ -318,12 +323,12 @@
}
// OK, there are bugs in recycler view which tries to bind views
- // without recycling them which would give us a chane to clean up.
+ // without recycling them which would give us a chance to clean up.
PageContentProvider boundProvider = mPageContentRepository
- .peekPageContentProvider(pageIndexInFile);
+ .peekPageContentProvider(pageIndexInFile);
if (boundProvider != null) {
PageContentView owner = (PageContentView) boundProvider.getOwner();
- owner.init(null, mMediaSize, mMinMargins);
+ owner.init(null, mEmptyState, mMediaSize, mMinMargins);
mPageContentRepository.releasePageContentProvider(boundProvider);
}
@@ -333,7 +338,7 @@
} else {
onSelectedPageNotInFile(pageInDocument);
}
- content.init(provider, mMediaSize, mMinMargins);
+ content.init(provider, mEmptyState, mMediaSize, mMinMargins);
View pageSelector = page.findViewById(R.id.page_selector);
pageSelector.setTag(myHolder);
@@ -384,7 +389,7 @@
mSelectedPages = selectedPages;
mSelectedPageCount = PageRangeUtils.getNormalizedPageCount(
mSelectedPages, mDocumentPageCount);
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
return mSelectedPages;
@@ -392,12 +397,12 @@
public void onPreviewAreaSizeChanged() {
if (mMediaSize != null) {
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
}
- private void updatePreviewAreaAndPageSize() {
+ private void updatePreviewAreaPageSizeAndEmptyState() {
final int availableWidth = mPreviewArea.getWidth();
final int availableHeight = mPreviewArea.getHeight();
@@ -419,7 +424,7 @@
final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth
/ pageAspectRatio) + 0.5f);
- // If the page does not fit entirely in a vertial direction,
+ // If the page does not fit entirely in a vertical direction,
// we shirk it but not less than the minimal page width.
final int pageContentMinHeight = (int) (mPreviewPageMinWidth / pageAspectRatio + 0.5f);
final int pageContentMaxHeight = Math.max(pageContentMinHeight,
@@ -448,6 +453,23 @@
mPreviewArea.setPadding(horizontalPadding, verticalPadding,
horizontalPadding, verticalPadding);
+
+ // Now update the empty state drawable, as it depends on the page
+ // size and is reused for all views for better performance.
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View content = inflater.inflate(R.layout.preview_page_loading, null, false);
+ content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
+ content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
+
+ Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ content.draw(canvas);
+
+ // Do not recycle the old bitmap if such as it may be set as an empty
+ // state to any of the page views. Just let the GC take care of it.
+ mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap);
}
private PageRange[] computeSelectedPages() {
@@ -718,7 +740,7 @@
private void recyclePageView(PageContentView page, int pageIndexInAdapter) {
PageContentProvider provider = page.getPageContentProvider();
if (provider != null) {
- page.init(null, null, null);
+ page.init(null, null, null, null);
mPageContentRepository.releasePageContentProvider(provider);
mBoundPagesInAdapter.remove(pageIndexInAdapter);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 022e0d0..c517f2d 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -23,6 +23,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
@@ -30,9 +31,12 @@
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.print.IPrintDocumentAdapter;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -74,6 +78,8 @@
import com.android.printspooler.model.PrintSpoolerService;
import com.android.printspooler.model.RemotePrintDocument;
import com.android.printspooler.model.RemotePrintDocument.RemotePrintDocumentInfo;
+import com.android.printspooler.renderer.IPdfEditor;
+import com.android.printspooler.renderer.PdfManipulationService;
import com.android.printspooler.util.MediaSizeUtils;
import com.android.printspooler.util.MediaSizeUtils.MediaSizeComparator;
import com.android.printspooler.util.PageRangeUtils;
@@ -81,8 +87,15 @@
import com.android.printspooler.widget.PrintContentView;
import com.android.printspooler.widget.PrintContentView.OptionsStateChangeListener;
import com.android.printspooler.widget.PrintContentView.OptionsStateController;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -114,14 +127,15 @@
private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
- private static final int STATE_CONFIGURING = 0;
- private static final int STATE_PRINT_CONFIRMED = 1;
- private static final int STATE_PRINT_CANCELED = 2;
- private static final int STATE_UPDATE_FAILED = 3;
- private static final int STATE_CREATE_FILE_FAILED = 4;
- private static final int STATE_PRINTER_UNAVAILABLE = 5;
- private static final int STATE_UPDATE_SLOW = 6;
- private static final int STATE_PRINT_COMPLETED = 7;
+ private static final int STATE_INITIALIZING = 0;
+ private static final int STATE_CONFIGURING = 1;
+ private static final int STATE_PRINT_CONFIRMED = 2;
+ private static final int STATE_PRINT_CANCELED = 3;
+ private static final int STATE_UPDATE_FAILED = 4;
+ private static final int STATE_CREATE_FILE_FAILED = 5;
+ private static final int STATE_PRINTER_UNAVAILABLE = 6;
+ private static final int STATE_UPDATE_SLOW = 7;
+ private static final int STATE_PRINT_COMPLETED = 8;
private static final int UI_STATE_PREVIEW = 0;
private static final int UI_STATE_ERROR = 1;
@@ -185,6 +199,7 @@
private ImageView mPrintButton;
private ProgressMessageController mProgressMessageController;
+ private MutexFileProvider mFileProvider;
private MediaSizeComparator mMediaSizeComparator;
@@ -196,7 +211,7 @@
private int mCurrentPageCount;
- private int mState;
+ private int mState = STATE_INITIALIZING;
private int mUiState = UI_STATE_PREVIEW;
@@ -256,9 +271,8 @@
setTitle(R.string.print_dialog);
setContentView(R.layout.print_activity);
- final MutexFileProvider fileProvider;
try {
- fileProvider = new MutexFileProvider(
+ mFileProvider = new MutexFileProvider(
PrintSpoolerService.generateFileForPrintJob(
PrintActivity.this, mPrintJob.getId()));
} catch (IOException ioe) {
@@ -267,12 +281,13 @@
}
mPrintPreviewController = new PrintPreviewController(PrintActivity.this,
- fileProvider);
+ mFileProvider);
mPrintedDocument = new RemotePrintDocument(PrintActivity.this,
IPrintDocumentAdapter.Stub.asInterface(documentAdapter),
- fileProvider, new RemotePrintDocument.DocumentObserver() {
+ mFileProvider, new RemotePrintDocument.DocumentObserver() {
@Override
public void onDestroy() {
+ setState(STATE_PRINT_CANCELED);
finish();
}
}, PrintActivity.this);
@@ -290,10 +305,17 @@
mPrintedDocument.start();
ensurePreviewUiShown();
+
+ setState(STATE_CONFIGURING);
}
@Override
public void onPause() {
+ if (mState == STATE_INITIALIZING) {
+ super.onPause();
+ return;
+ }
+
if (isFinishing()) {
PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
@@ -341,9 +363,13 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mState == STATE_INITIALIZING) {
+ return super.onKeyUp(keyCode, event);
+ }
+
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.isTracking() && !event.isCanceled()) {
- if (mPrintPreviewController != null&&mPrintPreviewController.isOptionsOpened()
+ if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
&& !hasErrors()) {
mPrintPreviewController.closeOptions();
} else {
@@ -357,7 +383,7 @@
@Override
public void onRequestContentUpdate() {
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
@@ -374,7 +400,7 @@
@Override
public void onActionPerformed() {
if (mState == STATE_UPDATE_FAILED
- && canUpdateDocument() && updateDocument(true, true)) {
+ && canUpdateDocument() && updateDocument(true)) {
ensurePreviewUiShown();
setState(STATE_CONFIGURING);
updateOptionsUi();
@@ -545,14 +571,13 @@
if (resultCode == RESULT_OK && data != null) {
setState(STATE_PRINT_COMPLETED);
updateOptionsUi();
- Uri uri = data.getData();
- mPrintedDocument.writeContent(getContentResolver(), uri);
+ final Uri uri = data.getData();
// Calling finish here does not invoke lifecycle callbacks but we
// update the print job in onPause if finishing, hence post a message.
mDestinationSpinner.post(new Runnable() {
@Override
public void run() {
- finish();
+ shredPagesAndFinish(uri);
}
});
} else if (resultCode == RESULT_CANCELED) {
@@ -696,7 +721,7 @@
// Update the content if needed.
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
@@ -828,7 +853,7 @@
if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
startCreateDocumentActivity();
} else {
- finish();
+ shredPagesAndFinish(null);
}
}
@@ -881,7 +906,7 @@
attributes.setMinMargins(defaults.getMinMargins());
}
- private boolean updateDocument(boolean preview, boolean clearLastError) {
+ private boolean updateDocument(boolean clearLastError) {
if (!clearLastError && mPrintedDocument.hasUpdateError()) {
return false;
}
@@ -890,6 +915,7 @@
mPrintedDocument.clearUpdateError();
}
+ final boolean preview = mState != STATE_PRINT_CONFIRMED;
final PageRange[] pages;
if (preview) {
pages = mPrintPreviewController.getRequestedPages();
@@ -900,7 +926,7 @@
final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
pages, preview);
- if (willUpdate) {
+ if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
// When the update is done we update the print preview.
mProgressMessageController.post();
return true;
@@ -947,7 +973,7 @@
mPrintPreviewController.closeOptions();
if (canUpdateDocument()) {
- updateDocument(false, false);
+ updateDocument(false);
}
if (!mPrintedDocument.isUpdating()) {
@@ -1421,7 +1447,7 @@
if (mCurrentPrinter.equals(printer)) {
setState(STATE_CONFIGURING);
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
ensurePreviewUiShown();
updateOptionsUi();
@@ -1480,6 +1506,18 @@
return true;
}
+ private void shredPagesAndFinish(final Uri writeToUri) {
+ new PageShredder(this, mPrintJob, mFileProvider, new Runnable() {
+ @Override
+ public void run() {
+ if (writeToUri != null) {
+ mPrintedDocument.writeContent(getContentResolver(), writeToUri);
+ }
+ finish();
+ }
+ }).shred();
+ }
+
private final class SpinnerItem<T> {
final T value;
final CharSequence label;
@@ -1930,7 +1968,7 @@
|| (becameActive && hasCapab) || (isActive && gotCapab));
if (updateNeeded && canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
updateOptionsUi();
@@ -2021,7 +2059,7 @@
}
if (canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
updateOptionsUi();
@@ -2146,7 +2184,7 @@
updateOptionsUi();
if (hadErrors && canUpdateDocument()) {
- updateDocument(true, false);
+ updateDocument(false);
}
}
}
@@ -2186,4 +2224,176 @@
updateOptionsUi();
}
}
+
+ private static final class PageShredder implements ServiceConnection {
+ private static final String TEMP_FILE_PREFIX = "print_job";
+ private static final String TEMP_FILE_EXTENSION = ".pdf";
+
+ private final Context mContext;
+
+ private final MutexFileProvider mFileProvider;
+
+ private final PrintJobInfo mPrintJob;
+
+ private final PageRange[] mPagesToShred;
+
+ private final Runnable mCallback;
+
+ public PageShredder(Context context, PrintJobInfo printJob,
+ MutexFileProvider fileProvider, Runnable callback) {
+ mContext = context;
+ mPrintJob = printJob;
+ mFileProvider = fileProvider;
+ mCallback = callback;
+ mPagesToShred = computePagesToShred(mPrintJob);
+ }
+
+ public void shred() {
+ // If we have only the pages we want, done.
+ if (mPagesToShred.length <= 0) {
+ mCallback.run();
+ return;
+ }
+
+ // Bind to the manipulation service and the work
+ // will be performed upon connection to the service.
+ Intent intent = new Intent(PdfManipulationService.ACTION_GET_EDITOR);
+ intent.setClass(mContext, PdfManipulationService.class);
+ mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ final IPdfEditor editor = IPdfEditor.Stub.asInterface(service);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ // It's OK to access the data members as they are
+ // final and this code is the last one to touch
+ // them as shredding is the very last step, so the
+ // UI is not interactive at this point.
+ shredPages(editor);
+ updatePrintJob();
+ } finally {
+ mContext.unbindService(PageShredder.this);
+ mCallback.run();
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ /* do nothing */
+ }
+
+ private void shredPages(IPdfEditor editor) {
+ File tempFile = null;
+ ParcelFileDescriptor src = null;
+ ParcelFileDescriptor dst = null;
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ File jobFile = mFileProvider.acquireFile(null);
+ src = ParcelFileDescriptor.open(jobFile, ParcelFileDescriptor.MODE_READ_WRITE);
+
+ // Open the document.
+ editor.openDocument(src);
+
+ // We passed the fd over IPC, close this one.
+ src.close();
+
+ // Drop the pages.
+ editor.removePages(mPagesToShred);
+
+ // Write the modified PDF to a temp file.
+ tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_EXTENSION,
+ mContext.getCacheDir());
+ dst = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_WRITE);
+ editor.write(dst);
+ dst.close();
+
+ // Close the document.
+ editor.closeDocument();
+
+ // Copy the temp file over the print job file.
+ jobFile.delete();
+ in = new FileInputStream(tempFile);
+ out = new FileOutputStream(jobFile);
+ Streams.copy(in, out);
+ } catch (IOException|RemoteException e) {
+ Log.e(LOG_TAG, "Error dropping pages", e);
+ } finally {
+ IoUtils.closeQuietly(src);
+ IoUtils.closeQuietly(dst);
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ }
+ }
+
+ private void updatePrintJob() {
+ // Update the print job pages.
+ final int newPageCount = PageRangeUtils.getNormalizedPageCount(
+ mPrintJob.getPages(), 0);
+ mPrintJob.setPages(new PageRange[]{PageRange.ALL_PAGES});
+
+ // Update the print job document info.
+ PrintDocumentInfo oldDocInfo = mPrintJob.getDocumentInfo();
+ PrintDocumentInfo newDocInfo = new PrintDocumentInfo
+ .Builder(oldDocInfo.getName())
+ .setContentType(oldDocInfo.getContentType())
+ .setPageCount(newPageCount)
+ .build();
+ mPrintJob.setDocumentInfo(newDocInfo);
+ }
+
+ private static PageRange[] computePagesToShred(PrintJobInfo printJob) {
+ List<PageRange> rangesToShred = new ArrayList<>();
+ PageRange previousRange = null;
+
+ final int pageCount = printJob.getDocumentInfo().getPageCount();
+
+ PageRange[] printedPages = printJob.getPages();
+ final int rangeCount = printedPages.length;
+ for (int i = 0; i < rangeCount; i++) {
+ PageRange range = PageRangeUtils.asAbsoluteRange(printedPages[i], pageCount);
+
+ if (previousRange == null) {
+ final int startPageIdx = 0;
+ final int endPageIdx = range.getStart() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ } else {
+ final int startPageIdx = previousRange.getEnd() + 1;
+ final int endPageIdx = range.getStart() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ }
+
+ if (i == rangeCount - 1) {
+ final int startPageIdx = range.getEnd() + 1;
+ final int endPageIdx = printJob.getDocumentInfo().getPageCount() - 1;
+ if (startPageIdx <= endPageIdx) {
+ PageRange removedRange = new PageRange(startPageIdx, endPageIdx);
+ rangesToShred.add(removedRange);
+ }
+ }
+
+ previousRange = range;
+ }
+
+ PageRange[] result = new PageRange[rangesToShred.size()];
+ rangesToShred.toArray(result);
+ return result;
+ }
+ }
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
index 2b5b41b..5d858ca 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
@@ -185,8 +185,10 @@
public void run() {
// At this point the other end will write to the file, hence
// we have to close it and reopen after the write completes.
- Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
- mHandler.enqueueOperation(operation);
+ if (mPageAdapter.isOpened()) {
+ Message operation = mHandler.obtainMessage(MyHandler.MSG_CLOSE);
+ mHandler.enqueueOperation(operation);
+ }
}
});
}
@@ -195,6 +197,7 @@
if (mPageAdapter.isOpened()) {
mPageAdapter.close(null);
}
+ mRecyclerView.setAdapter(null);
mPageAdapter.destroy();
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index 23a01bd..e2ae758 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -17,17 +17,15 @@
package com.android.printspooler.widget;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Margins;
import android.util.AttributeSet;
-import android.util.TypedValue;
import android.view.View;
import com.android.printspooler.model.PageContentRepository;
-import com.android.printspooler.model.PageContentRepository.PageContentProvider;
import com.android.printspooler.model.PageContentRepository.RenderSpec;
+import com.android.printspooler.model.PageContentRepository.PageContentProvider;
/**
* This class represents a page in the print preview list. The width of the page
@@ -37,35 +35,20 @@
*/
public class PageContentView extends View
implements PageContentRepository.OnPageContentAvailableCallback {
-
- private final ColorDrawable mEmptyState;
-
private PageContentProvider mProvider;
private MediaSize mMediaSize;
private Margins mMinMargins;
+ private Drawable mEmptyState;
+
private boolean mContentRequested;
private boolean mNeedsLayout;
public PageContentView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- TypedValue typedValue = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.textColorPrimary,
- typedValue, true);
-
- mEmptyState = new ColorDrawable(typedValue.data);
-
- setBackground(mEmptyState);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- requestPageContentIfNeeded();
}
@Override
@@ -85,15 +68,19 @@
return mProvider;
}
- public void init(PageContentProvider provider, MediaSize mediaSize, Margins minMargins) {
+ public void init(PageContentProvider provider, Drawable emptyState,
+ MediaSize mediaSize, Margins minMargins) {
final boolean providerChanged = (mProvider == null)
? provider != null : !mProvider.equals(provider);
+ final boolean loadingDrawableChanged = (mEmptyState == null)
+ ? mEmptyState != null : !mEmptyState.equals(emptyState);
final boolean mediaSizeChanged = (mMediaSize == null)
? mediaSize != null : !mMediaSize.equals(mediaSize);
final boolean marginsChanged = (mMinMargins == null)
? minMargins != null : !mMinMargins.equals(minMargins);
- if (!providerChanged && !mediaSizeChanged && !marginsChanged) {
+ if (!providerChanged && !mediaSizeChanged
+ && !marginsChanged && !loadingDrawableChanged) {
return;
}
@@ -101,6 +88,7 @@
mMediaSize = mediaSize;
mMinMargins = minMargins;
+ mEmptyState = emptyState;
mContentRequested = false;
mNeedsLayout = mNeedsLayout || mediaSizeChanged || marginsChanged;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 17593fe..6d08970 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -70,7 +70,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 110;
+ private static final int DATABASE_VERSION = 111;
private Context mContext;
private int mUserHandle;
@@ -1770,6 +1770,24 @@
upgradeVersion = 110;
}
+ if (upgradeVersion < 111) {
+ // reset ringer mode, so it doesn't force zen mode to follow
+ if (mUserHandle == UserHandle.USER_OWNER) {
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+ + " VALUES(?,?);");
+ loadSetting(stmt, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ }
+ upgradeVersion = 111;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d4ebb01..b94a258 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -176,6 +176,7 @@
android:theme="@style/RecentsStyle"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
+ android:resumeWhilePausing="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.systemui.TOGGLE_RECENTS" />
@@ -196,6 +197,8 @@
android:label="@string/accessibility_desc_recent_apps"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
+ android:stateNotNeeded="true"
+ android:resumeWhilePausing="true"
android:theme="@style/RecentsTheme">
<intent-filter>
<action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml
new file mode 100644
index 0000000..a571cbc
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0" android:toYDelta="10%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="350" />
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.6666666666"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0%" android:toYDelta="-8.8888888888%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="1.1111111111"
+ android:fromYScale="1.0" android:toYScale="1.1111111111"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="350"
+ android:duration="350" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml
new file mode 100644
index 0000000..f0fd684
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_cubic"
+ android:duration="150"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@android:interpolator/fast_out_slow_in"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml
new file mode 100644
index 0000000..170ac82
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="110%" android:toYDelta="0%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_quint"
+ android:startOffset="50"
+ android:duration="250" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml
new file mode 100644
index 0000000..46045ac
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="0%" android:toYDelta="10%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_quint"
+ android:duration="300" />
+
+ <translate android:fromYDelta="10%" android:toYDelta="0%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_quint"
+ android:startOffset="300"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml
new file mode 100644
index 0000000..ad5341b
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="0%" android:toYDelta="110%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/accelerate_quint"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml
new file mode 100644
index 0000000..7687f02
--- /dev/null
+++ b/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="0.6" android:toAlpha="1.0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:startOffset="75"
+ android:duration="150"/>
+
+ <scale android:fromXScale="0.9" android:toXScale="1.0"
+ android:fromYScale="0.9" android:toYScale="1.0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:startOffset="75"
+ android:duration="225" />
+</set>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/recents_button_bg.xml b/packages/SystemUI/res/drawable/recents_button_bg.xml
index a4cb088..7456365 100644
--- a/packages/SystemUI/res/drawable/recents_button_bg.xml
+++ b/packages/SystemUI/res/drawable/recents_button_bg.xml
@@ -15,4 +15,5 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="?android:attr/colorControlHighlight" />
\ No newline at end of file
+ android:color="#40ffffff">
+</ripple>
diff --git a/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
new file mode 100644
index 0000000..7ca8c40
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_vpn_ic.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="17.0dp"
+ android:height="17.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.700000,10.000000c-0.800000,-2.300000 -3.000000,-4.000000 -5.700000,-4.000000c-3.300000,0.000000 -6.000000,2.700000 -6.000000,6.000000s2.700000,6.000000 6.000000,6.000000c2.600000,0.000000 4.800000,-1.700000 5.700000,-4.000000L17.000000,14.000000l0.000000,4.000000l4.000000,0.000000l0.000000,-4.000000l2.000000,0.000000l0.000000,-4.000000L12.700000,10.000000zM7.000000,14.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000c0.000000,-1.100000 0.900000,-2.000000 2.000000,-2.000000s2.000000,0.900000 2.000000,2.000000C9.000000,13.100000 8.100000,14.000000 7.000000,14.000000z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 1ef9cad..4b68e77 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,6 +23,6 @@
android:textSize="16sp"
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-light"
+ android:fontFamily="sans-serif"
android:background="#80000000"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 347c8a9..5889c55 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -25,6 +25,13 @@
android:gravity="center_vertical"
android:orientation="horizontal"
>
+ <ImageView
+ android:id="@+id/vpn"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:paddingEnd="6dp"
+ android:src="@drawable/stat_sys_vpn_ic"
+ />
<FrameLayout
android:id="@+id/wifi_combo"
android:layout_height="wrap_content"
@@ -36,6 +43,12 @@
android:layout_width="wrap_content"
/>
</FrameLayout>
+ <View
+ android:id="@+id/wifi_signal_spacer"
+ android:layout_width="4dp"
+ android:layout_height="4dp"
+ android:visibility="gone"
+ />
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index 351177b..ef85847 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -64,9 +64,4 @@
/>
</LinearLayout>
- <com.android.systemui.statusbar.NotificationScrimView
- android:id="@+id/scrim_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index ef4e27c..6b829e5 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -59,9 +59,4 @@
android:layout_height="match_parent"
/>
- <com.android.systemui.statusbar.NotificationScrimView
- android:id="@+id/scrim_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
</com.android.systemui.statusbar.ExpandableNotificationRow>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 09e541f..29fec41 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -26,24 +26,6 @@
android:fitsSystemWindows="true"
android:descendantFocusability="afterDescendants">
- <FrameLayout android:id="@+id/brightness_mirror"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="wrap_content"
- android:layout_gravity="@integer/notification_panel_layout_gravity"
- android:paddingLeft="@dimen/notification_side_padding"
- android:paddingRight="@dimen/notification_side_padding"
- android:visibility="gone">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:elevation="2dp"
- android:background="@drawable/brightness_mirror_background">
- <include layout="@layout/quick_settings_brightness_dialog"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
- </FrameLayout>
- </FrameLayout>
-
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/backdrop"
android:layout_width="match_parent"
@@ -69,6 +51,24 @@
android:layout_width="match_parent"
android:layout_height="@dimen/status_bar_height" />
+ <FrameLayout android:id="@+id/brightness_mirror"
+ android:layout_width="@dimen/notification_panel_width"
+ android:layout_height="wrap_content"
+ android:layout_gravity="@integer/notification_panel_layout_gravity"
+ android:paddingLeft="@dimen/notification_side_padding"
+ android:paddingRight="@dimen/notification_side_padding"
+ android:visibility="gone">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:elevation="2dp"
+ android:background="@drawable/brightness_mirror_background">
+ <include layout="@layout/quick_settings_brightness_dialog"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </FrameLayout>
+ </FrameLayout>
+
<com.android.systemui.statusbar.phone.PanelHolder
android:id="@+id/panel_holder"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index df6e9fd..ee27bb2 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Това у-во се управлява от:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПотр. ви профил се управлява от:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистр. ви може да наблюдава акт. ви в мрежата, вкл. имейлите, прилож. и защитените уебсайтове. За още информация се свържете с него.\n\nСъщо така дадохте на <xliff:g id="APPLICATION">%3$s</xliff:g> разрешение да настрои връзка с VPN. Приложението може да наблюдава и акт. в мрежата."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"У-вото се управлява от:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПотр. ви профил се управлява от:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистраторът ви може да наблюдава акт. ви в мрежата, вкл. имейлите, прилож. и защитените уебсайтове. За още информация се свържете с него.\n\nСъщо така сте свързани с VPN (<xliff:g id="APPLICATION">%3$s</xliff:g>). Доставчикът ви на услуги за VPN може да наблюдава и акт. ви в мрежата."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройството ще остане заключено, докато не го отключите ръчно"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Получавайте известия по-бързо"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Вижте известията, преди да отключите"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Няма нужда"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Настройване"</string>
<string name="muted_by" msgid="6147073845094180001">"Заглушено от <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 83a6ba9..812b19c 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"এই ডিভাইসটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nআপনার প্রোফাইলটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nআপনার প্রশাসক ইমেল,অ্যাপ্লিকেশান ও নিরাপদ ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক ক্রিয়াকলাপ নিরীক্ষণ করতে সক্ষম। আরো তথ্যের জন্য, আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।\n\nআপনি \"<xliff:g id="APPLICATION">%3$s</xliff:g>\"-কে একটি VPN সংযোগ সেট আপ করার অনুমতিও দিয়েছেন। এই অ্যাপ্লিকেশান নেটওয়ার্ক ক্রিয়াকলাপও নিরীক্ষণ করতে পারে।"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"এই ডিভাইসটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nআপনার প্রোফাইলটি পরিচালনা করছে:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nআপনার প্রশাসক ইমেল,অ্যাপ্লিকেশান ও নিরাপদ ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক ক্রিয়াকলাপ নিরীক্ষণ করতে সক্ষম। আরো তথ্যের জন্য, আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।\n\nএছাড়াও, আপনি একটি VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") এ সংযুক্ত আছেন। আপনার VPN পরিষেবা প্রদানকারী নেটওয়ার্ক ক্রিয়াকলাপও নিরীক্ষণ করতে পারে।"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"আপনি নিজে আনলক না করা পর্যন্ত ডিভাইসটি লক হয়ে থাকবে"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"বিজ্ঞপ্তিগুলি আরো দ্রুত পান"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"আপনি আনলক করার আগে ওগুলো দেখুন"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"না থাক"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"সেট আপ"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> দ্বারা নিঃশব্দ করা হয়েছে"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 2197cbd3..89911ad 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -69,7 +69,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"Ukládání snímku obrazovky..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"Probíhá ukládání snímku obrazovky."</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky zachycen."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string>
<string name="screenshot_failed_text" msgid="1260203058661337274">"Snímek obrazovky nelze pořídit kvůli nedostatku místa, nebo to aplikace či vaše organizace zakazuje."</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 126b3f6..5226b9c 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -348,20 +348,16 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"VPN sarera konektatuta zaude (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nVPN zerbitzu-hornitzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne."</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne.Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexio bat ezartzeko baimena eman diozu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" aplikazioari. Aplikazioak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
- <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
- <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune segurak barne.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webgune seguruak barne. Informazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+ <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jo administratzailearengana."</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak gailua eta sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne.\n\nInformazio gehiago lortzeko, jo administratzailearengana."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Honek kudeatzen du profila:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN konexioa konfiguratzeko \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" baimena eman duzu. Aplikazio horrek ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Honek kudeatzen du gailua:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nHonek kudeatzen du profila:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdministratzaileak sarean egiten dituzun jarduerak kontrola ditzake, mezuak, aplikazioak eta webgune seguruak barne. Info. gehiago lortzeko, jo administratzailearengana.\n\nGainera, VPN sare batera konektatuta zaude (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). VPN hornitzaileak ere kontrola ditzake sarean egiten dituzun jarduerak."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Gailua blokeatuta egongo da eskuz desblokeatu arte"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Eskuratu jakinarazpenak azkarrago"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Ikusi desblokeatu baino lehen"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ez, eskerrik asko"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Konfiguratu"</string>
<string name="muted_by" msgid="6147073845094180001">"Audioa desaktibatu da (<xliff:g id="THIRD_PARTY">%1$s</xliff:g>)"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f3479af..9f63781 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nمدیریت نمایهتان توسط:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nسرپرستتان میتواند فعالیت شبکهتان را کنترل کند از جمله ایمیلها، برنامهها و وبسایتهای ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به «<xliff:g id="APPLICATION">%3$s</xliff:g>» اجازه دادید اتصال VPN را تنظیم کند. این برنامه میتواند فعالیت شبکه را نیز کنترل کند."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"مدیریت این دستگاه توسط:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nمدیریت نمایهتان توسط:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nسرپرستتان میتواند فعالیت شبکهتان را کنترل کند از جمله ایمیلها، برنامهها و وبسایتهای ایمن. برای کسب اطلاعات بیشتر، با سرپرستتان تماس بگیرید.\n\nهمچنین، به VPN («<xliff:g id="APPLICATION">%3$s</xliff:g>») وصل هستید. ارائهدهنده سرویس VPN شما میتواند فعالیت شبکه را نیز کنترل کند."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"دستگاه قفل باقی میماند تا زمانی که قفل آن را به صورت دستی باز کنید"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"دریافت سریعتر اعلانها"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"قبل از باز کردن قفل آنها را مشاهده کنید"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"خیر، سپاسگزارم"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"راهاندازی"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> آن را بیصدا کرد"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4e595df..e2dd843 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Laitteen hallinnoija: \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfiilisi hallinnoija: \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nJärjestelmänvalvoja voi valvoa toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nAnnoit sovellukselle <xliff:g id="APPLICATION">%3$s</xliff:g> luvan VPN-yhteyden määrittämiseen. Myös se voi valvoa toimiasi."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Laitteen hallinnoija: \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfiilisi hallinnoija: \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nJärjestelmänvalvoja voi valvoa toimiasi verkossa, esimerkiksi sähköpostin, sovellusten ja turvallisten verkkosivustojen käyttöä. Saat lisätietoja järjestelmänvalvojalta.\n\nKäytät VPN-yhteyttä (<xliff:g id="APPLICATION">%3$s</xliff:g>). VPN-palveluntarjoaja voi myös valvoa toimiasi."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Laite pysyy lukittuna, kunnes se avataan käsin"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Näe ilmoitukset nopeammin"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Näytä ennen lukituksen avaamista"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ei kiitos"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Määritä asetukset"</string>
<string name="muted_by" msgid="6147073845094180001">"Mykistänyt <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0282d02..71f042d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -338,7 +338,7 @@
<string name="media_projection_action_text" msgid="8470872969457985954">"Commencer maintenant"</string>
<string name="empty_shade_text" msgid="708135716272867002">"Aucune notification"</string>
<string name="device_owned_footer" msgid="3802752663326030053">"Il est possible que cet appareil soit surveillé."</string>
- <string name="profile_owned_footer" msgid="8021888108553696069">"Ce profil peut être contrôlé"</string>
+ <string name="profile_owned_footer" msgid="8021888108553696069">"le profil peut être contrôlé"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Le réseau peut être surveillé"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Surveillance d\'appareils"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Contrôle de profil"</string>
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Appareil géré par : \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par : \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut surveiller votre activité réseau (courriels, applications et sites sécurisés). Communiquez avec votre administrateur.\n\nEn outre, vous avez autorisé <xliff:g id="APPLICATION">%3$s</xliff:g> à créer une connexion RPV. Cette application peut aussi surveiller l\'activité réseau."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Appareil géré par : \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par : \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut surveiller l\'act. de votre appareil et votre act. réseau (courriels, applications et sites sécurisés). Communiquez avec votre administrateur.\n\nVous êtes aussi connecté à un RPV (<xliff:g id="APPLICATION">%3$s</xliff:g>). Votre admin RPV peut lui aussi surveiller votre act. réseau."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Voir les notifications plus rapidement"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
<string name="muted_by" msgid="6147073845094180001">"Mis en sourdine par <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index daaace4..a85b209 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Appareil géré par :\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par :\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut contrôler votre activité réseau (e-mails, applications et sites sécurisés). Pour en savoir plus, contactez votre admin.\n\nVous avez donné à l\'appli \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" l\'autorisation de configurer une connexion VPN. Cette appli peut contrôler votre activité réseau."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Appareil géré par :\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil géré par :\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nVotre administrateur peut contrôler votre activité réseau (e-mails, applications et sites sécurisés). Pour en savoir plus, contactez votre administrateur.\n\nVous êtes aussi connecté à un VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Votre fournisseur de services VPN peut également contrôler l\'activité réseau."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"L\'appareil restera verrouillé jusqu\'à ce que vous le déverrouilliez manuellement."</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Recevoir les notifications plus vite"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Afficher les notifications avant de déverrouiller l\'appareil"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Non, merci"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurer"</string>
<string name="muted_by" msgid="6147073845094180001">"Son coupé par : <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 11f3aa8..af20b98 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Լրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև «<xliff:g id="APPLICATION">%3$s</xliff:g>»-ին թույլատրել եք ստեղծել VPN: Այն նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Սարքի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nՊրոֆիլի կառավարիչն է՝\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը՝ նամակները, ծրագրերը և վստահելի կայքերը: Այլ տեղեկությունների համար դիմեք ադմինիստրատորին:\n\nԴուք նաև միացած եք VPN-ին («<xliff:g id="APPLICATION">%3$s</xliff:g>»): VPN ծառայություն մատուցողը նույնպես կարող է վերահսկել ցանցային գործունեությունը:"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Ստանալ ծանուցումներն ավելի արագ"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Տեսեք դրանք՝ մինչև ապակողպելը"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ոչ, շնորհակալություն"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Կարգավորել"</string>
<string name="muted_by" msgid="6147073845094180001">"Համրեցվել է <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ի կողմից"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0404ce5..f1aa72c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -355,15 +355,11 @@
<string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"このプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN接続を設定する権限を「<xliff:g id="APPLICATION">%2$s</xliff:g>」に付与しているため、このアプリもネットワークアクティビティを監視できます。"</string>
<string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"このプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%2$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもネットワークアクティビティを監視できます。"</string>
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN接続を設定する権限を「<xliff:g id="APPLICATION">%3$s</xliff:g>」に付与しているため、このアプリもネットワークアクティビティを監視できます。"</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%3$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもあなたのネットワークアクティビティを監視できます。"</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"この端末は次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nあなたのプロフィールは次の組織によって管理されています。\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n管理者はあなたのネットワークアクティビティ(メール、アプリ、保護されたウェブサイトなど)を監視できます。詳しくは管理者にお問い合わせください。\n\nまた、VPN(「<xliff:g id="APPLICATION">%3$s</xliff:g>」)に接続しているため、VPNサービスプロバイダもネットワークアクティビティを監視できます。"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"手動でロックを解除するまでロックされたままとなります"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"通知をすばやく確認できます"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"ロックを解除する前にご確認ください"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"キャンセル"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>によりミュートになっています"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 30b6d67..e7b272b 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ მიანიჭეთ „<xliff:g id="APPLICATION">%3$s</xliff:g>“-ს VPN კავშირის დაყენება. ამ აპს ასევე შეუძლია ქსელის მონიტორინგი."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ამ მოწყობილობის მმართველია:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nთქვენი პროფილის მმართველია:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი მოწყობილობისა და ქსელის აქტივობის მონიტორინგი, მათ შორის ელფოსტის, აპების და უსაფრთხო საიტების. დამატებითი ინფორმაციისათვის, დაუკავშირდით ადმინისტრატორს.\n\nასევე, თქვენ დაკავშირებული ხართ VPN-თან („<xliff:g id="APPLICATION">%3$s</xliff:g>“). თქვენს VPN სერვისის მომწოდებელს ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"შეტყობინებების უფრო სწრაფად მიღება"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"იხილეთ განბლოკვამდე"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"არა, გმადლობთ"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"დაყენება"</string>
<string name="muted_by" msgid="6147073845094180001">"დადუმებულია <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ის მიერ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index 055bee6..e7e7119 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Бұл құрылғыны басқаратын:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофиліңізді басқаратын:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nӘкімші желілік белс-ті, соның ішінде, эл. хаб-ды, қол-ды және қорғалған веб-сайттарды бақылай алады. Қосымша ақпар. алу үшін әкімшіге хаб-з.\n\nСондай-ақ, сіз «<xliff:g id="APPLICATION">%3$s</xliff:g>» VPN байланысын орнату рұқсатын бердіңіз. Бұл қолданба да желілік белсенділікті бақылай алады."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Бұл құр. басқаратын:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофиліңізді басқаратын:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nӘкімші желілік белсенділікті, соның ішінде, эл. хаб-ды, қолд-ды және қорғалған веб-сайттарды бақылай алады. Қосымша ақпарат алу үшін әкімшіге хаб-ңыз.\n\nСондай-ақ, VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") қызметіне қосылғансыз. VPN қызметін жеткізуші де желілік белсенділікті бақылай алады."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Қолмен бекітпесін ашқанша құрылғы бекітілген күйде қалады"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Хабарландыруларды тезірек алу"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Бекітпесін ашу алдында оларды көру"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жоқ, рақмет"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Реттеу"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> үнін өшірген"</string>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 252f356..61d4289 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ៖\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nប្រវត្តិរូបរបស់អ្នកត្រូវបានគ្រប់គ្រង៖\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nអ្នកគ្រប់គ្រងរបស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញ រួមមានអ៊ីមែល កម្មវិធី និងតំបន់បណ្ដាញមានសុវត្ថិភាព។ ចំពោះព័ត៌មានបន្ថែម ទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក។\n\nអ្នកបានផ្ដល់សិទ្ធិ \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ឲ្យកំណត់ការភ្ជាប់ VPN ។ កម្មវិធីនេះអាចតាមដានសកម្មភាពបណ្ដាញផងដែរ។"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ឧបករណ៍នេះត្រូវបានគ្រប់គ្រងដោយ៖\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nប្រវត្តិរូបរបស់អ្នកត្រូវបានគ្រប់គ្រងដោយ៖\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nអ្នកគ្រប់គ្រងរបស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញរបស់អ្នក រួមមានអ៊ីមែល, កម្មវិធី និងតំបន់បណ្ដាញមានសុវត្ថិភាព។ ចំពោះព័ត៌មានបន្ថែម ទាក់ទងអ្នកគ្រប់គ្រងរបស់អ្នក។\n\nអ្នកក៏បានភ្ជាប់ទៅ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") ។ ក្រុមហ៊ុនផ្ដល់សេវាកម្ម VPN របស់អ្នកអាចតាមដានសកម្មភាពបណ្ដាញបានផងដែរ។"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ឧបករណ៍នឹងចាក់សោរហូតដល់អ្នកដោះសោដោយដៃ"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"ទទួលបានការជូនដំណឹងកាន់តែលឿន"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"ឃើញពួកវាមុនពេលដោះសោ"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"ទេ អរគុណ!"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"រៀបចំ"</string>
<string name="muted_by" msgid="6147073845094180001">"បានបិទសំឡេងដោយ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 9d424ae..e73cbde 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"기기 관리자:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n프로필 관리자:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n관리자는 이메일, 앱, 보안 웹사이트를 비롯한 내 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 \'<xliff:g id="APPLICATION">%3$s</xliff:g>\'에 VPN 연결을 설정할 수 있는 권한을 부여했습니다. 이 앱에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"기기 관리자:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n프로필 관리자:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n관리자는 이메일, 앱, 보안 웹사이트를 비롯한 내 네트워크 활동을 모니터링할 수 있습니다. 자세한 정보는 관리자에게 문의하세요.\n\n또한 현재 VPN(\'<xliff:g id="APPLICATION">%3$s</xliff:g>\')에 연결되어 있습니다. VPN 서비스 제공업체에서도 네트워크 활동을 모니터링할 수 있습니다."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"수동으로 잠금 해제할 때까지 기기가 잠금 상태로 유지됩니다."</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"알림을 더욱 빠르게 받기"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"잠금 해제하기 전에 알림을 봅니다."</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"사용 안함"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"설정"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>에서 알림음 음소거"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index 1827c13..a96c88a 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -381,13 +381,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Бул түзмөктү төмөнкү башк-т:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофилиңизди төмөнкү башк-т:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдмин-ңуздун тармак ар-ңизди, анын ичинде email-дер, колд-лор жана коопсуз вебс-ды, көз-дөө мүмк-гү бар. Дагы маалымат үчүн, админ-ңузга кайр-з.\n\n\"<xliff:g id="APPLICATION">%3$s</xliff:g>\" VPN туташуусун орнотуусуна да уруксат бердиңиз. Бул колдонмо тармак аракетин да көзөмөлдөй алат."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Түзмөктү тө-кү башк-т:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nПрофилди тө-кү башк-т:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдмин-ңуздун тармак ар-ңизди, анын ичинде email-дер, колд-лор жана коопсуз вебс-ды, көзөмөлдөө мүмкүнчүлүгү бар. Дагы маалымат үчүн, админ-ңузга кайрылыңыз.\n\nСиз VPN-ге (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") да туташкансыз. VPN тейлөөчүңүз да тармак аракетин көзөмөлдөй алат."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Түзмөктүн кулпусу кол менен ачылмайынча кулпуланган бойдон алат"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Эскертмелерди тезирээк алуу"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Аларды кулпудан чыгараардан мурун көрүңүз"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Жок, рахмат"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Орнотуу"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> тарабынан үнсүздөлдү"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 6f41766..468f717 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nໂປຣໄຟລ໌ຂອງທ່ານແມ່ນຖືກຈັດການໂດຍ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nຜູ່ເບິ່ງແຍງຂອງທ່ານມີຄວາມສາມາດໃນການຕິດຕາມການເຄື່ອນໄຫວໃນເຄືອຂ່າຍຂອງທ່ານໄດ້ ຮວມເຖິງ: ອີເມວ, ແອັບຯ ແລະເວັບໄຊທີ່ເຂົ້າລະຫັດ. ສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ໃຫ້ຕິດຕໍ່ຜູ່ເບິ່ງແຍງລະບົບຂອງທ່ານ.\n\nນອກຈາກນັ້ນ, ທ່ານໄດ້ອະນຸຍາດໃຫ້ \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ສາມາດຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ໄດ້. ແອັບຯນີ້ສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍຂອງທ່ານໄດ້ເຊັ່ນກັນ."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nໂປຣໄຟລ໌ຂອງທ່ານແມ່ນຖືກຈັດການໂດຍ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nຜູ່ເບິ່ງແຍງຂອງທ່ານມີຄວາມສາມາດໃນການຕິດຕາມການເຄື່ອນໄຫວໃນເຄືອຂ່າຍຂອງທ່ານໄດ້ ຮວມເຖິງ: ອີເມວ, ແອັບຯ ແລະເວັບໄຊທີ່ເຂົ້າລະຫັດ. ສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ໃຫ້ຕິດຕໍ່ຜູ່ເບິ່ງແຍງລະບົບຂອງທ່ານ.\n\nນອກຈາກນັ້ນ, ທ່ານໄດ້ເຊື່ອມຕໍ່ຫາ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). ຜູ່ໃຫ້ບໍລິການ VPN ຂອງທ່ານສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍໄດ້ເຊັ່ນກັນ."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"ຮັບເອົາການແຈ້ງເຕືອນໄວຂຶ້ນ"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"ເບິ່ງພວກມັນກ່ອນທ່ານຈະປົດລັອກ"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"ບໍ່, ຂອບໃຈ"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"ຕັ້ງຄ່າ"</string>
<string name="muted_by" msgid="6147073845094180001">"ຖືກປິດສຽງໂດຍ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 12ab9e8..293b028 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -266,7 +266,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ടെതറിംഗ്"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ഹോട്ട്സ്പോട്ട്"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"അറിയിപ്പുകൾ"</string>
- <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ഫ്ലാഷ്ലൈറ്റ്"</string>
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ഫ്ലാഷ്ലൈറ്റ്"</string>
<string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"സെല്ലുലാർ ഡാറ്റ"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ഡാറ്റ ഉപയോഗം"</string>
<string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ശേഷിക്കുന്ന ഡാറ്റ"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 1d8e11e..f6c6f8a 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -350,10 +350,10 @@
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"हे डिव्हाइस याद्वारे व्यवस्थापित केले जाते:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइट यासह आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN शी कनेक्ट केले आहे (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
<string name="monitoring_description_profile_owned" msgid="2370062794285691713">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या डिव्हाइसचे आणि नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो.\n\nअधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा."</string>
<string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या डिव्हाइसचे आणि नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो.\n\nअधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, आपण एका VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे परीक्षण देखील करू शकतो."</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतथापि, आपण एका VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"हे प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, VPN कनेक्शन सेट करण्यासाठी आपण \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" ला परवानगी दिली आहे. हा अॅप नेटवर्क क्रियाकलापाचे परीक्षण देखील करू शकतो."</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"हे डिव्हाइस याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nआपले प्रोफाईल याद्वारे व्यवस्थापित केले आहे:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nआपला प्रशासक ईमेल, अॅप्स आणि सुरक्षित वेबसाइटसह, आपल्या नेटवर्क क्रियाकलापाचे परीक्षण करण्यास सक्षम आहे. अधिक माहितीसाठी, आपल्या प्रशासकाशी संपर्क साधा.\n\nतसेच, आपण एका VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") शी कनेक्ट केलेले आहे. आपला VPN सेवा प्रदाता नेटवर्क क्रियाकलापाचे देखील परीक्षण करू शकतो."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"आपण व्यक्तिचलितपणे अनलॉक करेपर्यंत डिव्हाइस लॉक केलेले राहील"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"सूचना अधिक जलद मिळवा"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"आपण अनलॉक करण्यापूर्वी त्यांना पहा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index df99613..0c0efb3 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Peranti ini diurus olh:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil anda diurus olh:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nPentadbir anda bkemampuan mmantau aktiviti rgkaian anda tmasuk e-mel, apl dan tapak web yg slmt. Untuk mdptkn maklumat lanjut, hubungi pentadbir anda.\n\nAnda jg mberi \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" kebenaran utk menyediakan smbungn VPN. Apl ini jg blh mmantau aktiviti rngkaian."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Peranti ini diurus olh:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil anda diurus olh:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nPentadbir anda blh mmantau pranti dn aktiviti rgkaian anda, tmasuk e-mel, apl dan tapak web yg slmt. Utk mdapatkan mklumat lanjut, hubungi pentadbir anda.\n\nAnda juga disambungkn ke VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Pmbekal perkhidmatan VPN anda jg blh memantau rangkaian aktiviti."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Peranti akan kekal terkunci sehingga anda membuka kunci secara manual"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Dapatkan pemberitahuan lebih cepat"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Lihat sebelum anda membuka kunci"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Tidak, terima kasih"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Sediakan"</string>
<string name="muted_by" msgid="6147073845094180001">"Diredam oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 8c866a9..df555a6 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"यस उपकरण र तपाईँको प्रोफाइल \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n र \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n ले व्यवस्थित गरिएको छ। तपाईँको प्रशासकले सञ्जाल गतिविधि निगरानी गर्न सक्षम छन् जस्तै इमेल, अनुप्रयोग र सुरक्षित वेबसाइट। थप जान्न प्रशासकलाई सम्पर्क गर्नुहोला।\n\nसाथै, तपाईँले VPN जडान स्थापित गर्न \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" अनुमति दिनुभयो। यो अनुप्रयोगले संजालको निगरानी पनि गर्न सक्छ।"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"यो उपकरणको व्यवस्थित \n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n ले गरेको छ। तपाईँको प्रोफाइल \n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n ले व्यवस्थित गरिएको छ। तपाईँको प्रशासकले सञ्जाल गतिविधि निगरानी गर्न सक्षम छन् जसमा इमेल, अनुप्रयोग र सुरक्षित वेबसाइट छ। थप जान्न प्रशासकलाई सम्पर्क गर्नुहोला।\n\nसाथै, तपाईँ VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") मा जडित हुनुहुन्छ। जुन सेवा प्रदायकले निगरानी गर्न सक्ने छन्।"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तपाईँले नखोले सम्म उपकरण बन्द रहनेछ"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"छिटो सूचनाहरू प्राप्त गर्नुहोस्"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"तपाईँले अनलक गर्नअघि तिनीहरूलाई हेर्नुहोस्"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"धन्यवाद पर्दैन"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"सेटअप गर्नुहोस्"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा मौन गरिएको"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 181f361..4180640 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nSeu perfil é gerenciado por:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, como e-mails, apps e sites seguros. Para mais informações, contate o administrador.\n\nVocê autorizou \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" a fazer conexões VPN e o provedor de serviços de VPN também pode monitorar atividades de rede."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Este dispositivo é gerenciado por:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nSeu perfil é gerenciado por:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nO administrador pode monitorar sua atividade na rede, como e-mails, apps e sites seguros. Para mais informações, contate o administrador.\n\nVocê está conectado a uma VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") e o provedor de serviços de VPN também pode monitorar atividades de rede."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Veja-as antes de desbloquear"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Não, obrigado"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Configurar"</string>
<string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9a41430..84cfff4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Устройством управляет организация:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nВашим профилем управляет организация:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с эл. почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nВы разрешили приложению \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" подключаться к VPN, и ему также доступны эти сведения."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Устройством управляет организация:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nВашим профилем управляет организация:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nАдминистратор может отслеживать вашу работу с почтой, приложениями и защищенными веб-сайтами. Обратитесь к нему за дополнительной информацией.\n\nУстройство подключено к сети VPN (<xliff:g id="APPLICATION">%3$s</xliff:g>). Поставщику услуг VPN видны ваши действия в Сети."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Устройство необходимо будет разблокировать вручную"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Быстрый доступ к уведомлениям"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Просматривайте уведомления на заблокированном экране."</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Закрыть"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Настроить"</string>
<string name="muted_by" msgid="6147073845094180001">"Звук отключен приложением \"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>\""</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bd667cf..c0b1b12 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -337,7 +337,7 @@
<string name="profile_owned_footer" msgid="8021888108553696069">"Huenda wasifu ukafuatiliwa"</string>
<string name="vpn_footer" msgid="2388611096129106812">"Huenda mtandao unafuatiliwa"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"Ufuatiliaji wa kifaa"</string>
- <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Ufuatiliaji wa wasifu"</string>
+ <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"Ufuatiliaji wasifu"</string>
<string name="monitoring_title" msgid="169206259253048106">"Ufuatiliaji wa mtandao"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Zima VPN"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Ondoa VPN"</string>
@@ -346,20 +346,16 @@
<string name="monitoring_description_legacy_vpn" msgid="4740349017929725435">"Umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%1$s</xliff:g>\").\n\nMtoa huduma wako wa VPN anaweza kufuatilia kifaa na shughuli za kifaa na mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti salama."</string>
<string name="monitoring_description_vpn_device_owned" msgid="696121105616356493">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao wako."</string>
<string name="monitoring_description_legacy_vpn_device_owned" msgid="649791650224064248">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
- <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli za mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
- <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli za mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
- <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao."</string>
- <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao wako ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
- <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli za mtandao."</string>
- <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli za mtandao."</string>
+ <string name="monitoring_description_profile_owned" msgid="2370062794285691713">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli kwenye mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="8685301493845456293">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia kifaa chako na shughuli kwenye mtandao, ikiwa ni pamoja na barua pepe na tovuti salama.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="847491346263295767">"Wasifu huu unasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli kwenye mtandao."</string>
+ <string name="monitoring_description_legacy_vpn_profile_owned" msgid="4095516964132237051">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%2$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli kwenye mtandao."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na na tovuti salama\n\nPia, uliruhusu \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" isanidi muunganisho wa VPN. Programu hii pia inaweza kufuatilia shughuli kwenye mtandao."</string>
+ <string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Kifaa hiki kinasimamiwa na:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nWasifu wako unasimamiwa na:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nMsimamizi wako anaweza kufuatilia shughuli zako kwenye mtandao, ikiwa ni pamoja na barua pepe, programu na tovuti salama. Kwa maelezo zaidi, wasiliana na msimamizi wako.\n\nPia, umeunganishwa kwenye VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\"). Mtoa huduma wako wa VPN pia anaweza kufuatilia shughuli kwenye mtandao."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Kifaa kitaendelea kuwa katika hali ya kufungwa hadi utakapokifungua mwenyewe"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Pata arifa kwa haraka"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Zitazame kabla hujafungua"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"La, asante"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Sanidi"</string>
<string name="muted_by" msgid="6147073845094180001">"Sauti imezimwa na <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 5aafb66..83477c0 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -33,6 +33,8 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">true</bool>
- <!-- Transposes the recents layout in landscape. -->
- <bool name="recents_transpose_layout_with_orientation">false</bool>
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">true</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 74a98fc..d3b5580 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -46,6 +46,9 @@
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.075</item>
+ <!-- The height of the search bar space. -->
+ <dimen name="recents_search_bar_space_height">72dp</dimen>
+
<!-- The fraction of the screen height where the clock on the Keyguard has its center. The
max value is used when no notifications are displaying, and the min value is when the
highest possible number of notifications are showing. -->
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index d8bb8d7d..fbeadcd 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -39,5 +39,10 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
+
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">false</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1c343a9..52700cc 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -83,7 +83,7 @@
<string name="accessibility_recent" msgid="1606470783629913980">"சமீபத்திய திரைகள்"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"தேடு"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"கேமரா"</string>
- <string name="accessibility_phone_button" msgid="6738112589538563574">"மொபைல்"</string>
+ <string name="accessibility_phone_button" msgid="6738112589538563574">"ஃபோன்"</string>
<string name="accessibility_unlock_button" msgid="128158454631118828">"திற"</string>
<string name="unlock_label" msgid="8779712358041029439">"திற"</string>
<string name="phone_label" msgid="2320074140205331708">"ஃபோனைத் திற"</string>
@@ -143,7 +143,7 @@
<string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ரோமிங்"</string>
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"வைஃபை"</string>
- <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM இல்லை."</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"சிம் இல்லை."</string>
<string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"புளூடூத் இணைப்பு முறை."</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"விமானப் பயன்முறை."</string>
<string name="accessibility_battery_level" msgid="7451474187113371965">"பேட்டரி சக்தி <xliff:g id="NUMBER">%d</xliff:g> சதவிகிதம் உள்ளது."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 2aa8f05..0c0149c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Bu cihazı yöneten kuruluş:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfilinizi yöneten kuruluş:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nYöneticiniz; e-postalar, uygulamalar ve güvenli web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilir. Daha fazla bilgi için yöneticinize başvurun.\n\nAyrıca \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" uygulamasına VPN kurma izni verdiniz. Bu uygulama da ağ etkinliğini izleyebilir."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Bu cihazı yöneten kuruluş:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfilinizi yöneten kuruluş:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nYöneticiniz; e-postalar, uygulamalar ve güvenli web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilir. Daha fazla bilgi için yöneticinize başvurun.\n\nAyrıca, bir VPN\'ye (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") bağlısınız. VPN hizmet sağlayıcınız da ağ etkinliğini izleyebilir."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Cihazınızın kilidini manuel olarak açmadıkça cihaz kilitli kalacak"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirimleri daha hızlı alın"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Kilidi açmadan bildirimleri görün"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Hayır, teşekkürler"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Kur"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> tarafından kapatıldı"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 4ab3171..162a280 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -286,7 +286,7 @@
<string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без сповіщень. Навіть без сигналів будильника."</string>
+ <string name="zen_no_interruptions_with_warning" msgid="4396898053735625287">"Без сповіщень і сигналів будильника."</string>
<string name="zen_no_interruptions" msgid="7970973750143632592">"Без сповіщень"</string>
<string name="zen_important_interruptions" msgid="3477041776609757628">"Лише пріоритетні сповіщення"</string>
<string name="zen_alarm_information_time" msgid="5235772206174372272">"Наступний сигнал: <xliff:g id="ALARM_TIME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 5bfac40..708607c 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"اس آلہ کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nآپ کے پروفائل کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی بشمول، ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کر سکتا ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ نے \"<xliff:g id="APPLICATION">%3$s</xliff:g>\" کو ایک VPN کنکشن ترتیب دینے کی اجازت دی ہے۔ یہ ایپ نیٹ ورک کی سرگرمی بھی مانیٹر کر سکتی ہے۔"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"اس آلہ کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nآپ کے پروفائل کا نظم کیا جاتا ہے بذریعہ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nآپ کا منتظم آپ کے نیٹ ورک کی سرگرمی، بشمول ای میلز، ایپس اور محفوظ ویب سائٹس کو مانیٹر کر سکتا ہے۔ مزید معلومات کیلئے، اپنے منتظم سے رابطہ کریں۔\n\nنیز، آپ ایک VPN (\"<xliff:g id="APPLICATION">%3$s</xliff:g>\") سے منسلک ہیں۔ آپ کا VPN سروس فراہم کنندہ نیٹ ورک کی سرگرمی کو بھی مانیٹر کر سکتا ہے۔"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"آلہ اس وقت تک مقفل رہے گا جب تک آپ دستی طور پر اسے غیر مقفل نہ کریں"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"تیزی سے اطلاعات حاصل کریں"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"غیر مقفل کرنے سے پہلے انہیں دیکھیں"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"نہیں شکریہ"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"ترتیب دیں"</string>
<string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> کے ذریعے خاموش کردہ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 8868213..7776269 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -355,13 +355,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil boshqaruvchisi:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi har-ni kuzatishi m-n. Qo‘sh. ma’l. olish u-n admin-ga murojaat qiling.\n\nSiz “<xliff:g id="APPLICATION">%3$s</xliff:g>” ilovasiga VPN ulanishini sozlash u-n ruxsat bergansiz. U ham tarmoqdagi faollikni kuzatishi m-n."</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"Bu qurilma boshqaruvchisi:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\nProfil boshqaruvchisi:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\nAdmin-ngiz tarmoqdagi faollik – e-pochta, ilova va xavfsiz veb-saytlardagi har-ni kuzatishi m-n.\n\nQo‘sh. ma’l. olish u-n admin-ga murojaat qiling. Siz VPN tarmog‘iga (“<xliff:g id="APPLICATION">%3$s</xliff:g>”) ulangansiz. VPN xizmati ta’minotchingiz ham tarmoqdagi faollikni kuzatishi m-n."</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Qurilma qo‘lda qulfdan chiqarilmaguncha qulflangan holatda qoladi"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirishnomalarni tezroq oling"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"Ularni qulfdan chiqarishdan oldin ko‘ring"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Yo‘q, kerak emas"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"Sozlash"</string>
<string name="muted_by" msgid="6147073845094180001">"“<xliff:g id="THIRD_PARTY">%1$s</xliff:g>” tomonidan ovozsiz qilingan"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7d6dc64..06cebb3 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -357,13 +357,9 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"此设备由以下单位管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的资料由以下单位管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理员可以监控您的网络活动,包括收发电子邮件、使用应用和浏览安全网站。若要了解详情,请与您的管理员联系。\n\n此外,您已授权“<xliff:g id="APPLICATION">%3$s</xliff:g>”设置VPN连接。此应用也可以监控网络活动。"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"此设备由以下单位管理:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的资料由以下单位管理:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理员可以监控您的网络活动,包括收发电子邮件、使用应用和浏览安全网站。若要了解详情,请与您的管理员联系。\n\n此外,您已连接到VPN(“<xliff:g id="APPLICATION">%3$s</xliff:g>”)。您的VPN服务提供商也可以监控您的网络活动。"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"在您手动解锁之前,设备会保持锁定状态"</string>
- <!-- no translation found for hidden_notifications_title (7139628534207443290) -->
- <skip />
- <!-- no translation found for hidden_notifications_text (2326409389088668981) -->
- <skip />
- <!-- no translation found for hidden_notifications_cancel (3690709735122344913) -->
- <skip />
- <!-- no translation found for hidden_notifications_setup (41079514801976810) -->
- <skip />
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"更快捷地查看通知"</string>
+ <string name="hidden_notifications_text" msgid="2326409389088668981">"无需解锁即可查看通知"</string>
+ <string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了"</string>
+ <string name="hidden_notifications_setup" msgid="41079514801976810">"设置"</string>
<string name="muted_by" msgid="6147073845094180001">"已被<xliff:g id="THIRD_PARTY">%1$s</xliff:g>设为静音"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2df414c..9b0bde1 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -338,7 +338,7 @@
<string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
<string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string>
<string name="device_owned_footer" msgid="3802752663326030053">"裝置可能會受到監控"</string>
- <string name="profile_owned_footer" msgid="8021888108553696069">"個人檔案可能會受到監控"</string>
+ <string name="profile_owned_footer" msgid="8021888108553696069">"個人檔案可能受到監控"</string>
<string name="vpn_footer" msgid="2388611096129106812">"網絡可能會受到監控"</string>
<string name="monitoring_title_device_owned" msgid="7121079311903859610">"裝置監控"</string>
<string name="monitoring_title_profile_owned" msgid="6790109874733501487">"個人檔案監控"</string>
@@ -357,7 +357,7 @@
<string name="monitoring_description_vpn_device_and_profile_owned" msgid="9193588924767232909">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您已授權「<xliff:g id="APPLICATION">%3$s</xliff:g>」設定 VPN 連線,因此這個應用程式也能監控您的網絡活動。"</string>
<string name="monitoring_description_legacy_vpn_device_and_profile_owned" msgid="6935475023447698473">"這部裝置的管理機構:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>\n您的個人檔案的管理機構:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>\n\n您的管理員可以監控您的網絡活動,包括電郵、應用程式及安全網站。如需瞭解詳情,請聯絡您的管理員。\n\n同時,由於您的裝置已與 VPN (「<xliff:g id="APPLICATION">%3$s</xliff:g>」) 連線,因此您的 VPN 服務供應商也能監控您的網絡活動。"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"裝置將保持上鎖,直到您手動解鎖"</string>
- <string name="hidden_notifications_title" msgid="7139628534207443290">"更快取得通知"</string>
+ <string name="hidden_notifications_title" msgid="7139628534207443290">"快速取得通知"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"解鎖前顯示"</string>
<string name="hidden_notifications_cancel" msgid="3690709735122344913">"不用了,謝謝"</string>
<string name="hidden_notifications_setup" msgid="41079514801976810">"設定"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 0e18979..5a1c318 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -134,10 +134,13 @@
<integer name="recents_animate_task_exit_to_home_duration">225</integer>
<!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_bar_exit_duration">125</integer>
+ <!-- The animation delay for animating the first task in. This should roughly be the animation
+ duration of the transition in to recents from home. -->
+ <integer name="recents_animate_task_enter_from_home_delay">150</integer>
<!-- The min animation duration for animating the task in when transitioning from home. -->
<integer name="recents_animate_task_enter_from_home_duration">275</integer>
<!-- The animation stagger to apply to each task animation when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_delay">10</integer>
+ <integer name="recents_animate_task_enter_from_home_stagger_delay">10</integer>
<!-- The short duration when animating in/out the lock to app button. -->
<integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
<!-- The long duration when animating in/out the lock to app button. -->
@@ -152,8 +155,10 @@
<integer name="recents_max_task_stack_view_dim">96</integer>
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
- <!-- Transposes the recents layout in landscape. -->
- <bool name="recents_transpose_layout_with_orientation">true</bool>
+ <!-- Transposes the search bar layout in landscape. -->
+ <bool name="recents_has_transposed_search_bar">true</bool>
+ <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
+ <bool name="recents_has_transposed_nav_bar">true</bool>
<!-- Whether to enable KeyguardService or not -->
<bool name="config_enableKeyguardService">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8cd4ce6..4495318 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -476,4 +476,12 @@
<fraction name="battery_subpixel_smoothing_right">0%</fraction>
<dimen name="battery_margin_bottom">0dp</dimen>
+
+ <!-- Extra padding between the mobile data type icon and the strength indicator when the data
+ type icon is wide. -->
+ <dimen name="wide_type_icon_start_padding">2dp</dimen>
+
+ <!-- Extra padding between the mobile data type icon and the strength indicator when the data
+ type icon is wide for the tile in quick settings. -->
+ <dimen name="wide_type_icon_start_padding_qs">3dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c7a91af..147efaf 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -756,6 +756,9 @@
<!-- Accessibility label for the button that opens the user switcher. -->
<string name="accessibility_multi_user_switch_switcher">Switch user</string>
+ <!-- Accessibility label for the button that opens the user switcher and announces the current user. -->
+ <string name="accessibility_multi_user_switch_switcher_with_current">Switch user, current user <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
+
<!-- Accessibility label for the button that opens the quick contact of the user. -->
<string name="accessibility_multi_user_switch_quick_contact">Show profile</string>
@@ -795,6 +798,12 @@
<!-- Notification when resuming an existing guest session: Action that continues with the current session [CHAR LIMIT=35] -->
<string name="guest_wipe_session_dontwipe">Yes, continue</string>
+ <!-- Title for add user confirmation dialog [CHAR LIMIT=30] -->
+ <string name="user_add_user_title" msgid="2108112641783146007">Add new user?</string>
+
+ <!-- Message for add user confirmation dialog - short version. [CHAR LIMIT=none] -->
+ <string name="user_add_user_message_short" msgid="1511354412249044381">When you add a new user, that person needs to set up their space.\n\nAny user can update apps for all other users. </string>
+
<!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_minutes">
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f8d0d9e..50ba68e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -487,7 +488,7 @@
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
mLockPatternUtils = new LockPatternUtils(mContext);
- mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
+ mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
// Assume keyguard is showing (unless it's disabled) until we know for sure...
mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
@@ -1142,7 +1143,6 @@
}
handleHide();
- sendUserPresentBroadcast();
}
private void sendUserPresentBroadcast() {
@@ -1313,6 +1313,7 @@
mHideAnimationRun = false;
updateActivityLockScreenState();
adjustStatusBarLocked();
+ sendUserPresentBroadcast();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
index 377fcc0..b86e67c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDualTileLabel.java
@@ -59,7 +59,7 @@
.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_horizontal);
mFirstLine = initTextView();
- mFirstLine.setPadding(mHorizontalPaddingPx, 0, 0, 0);
+ mFirstLine.setPadding(mHorizontalPaddingPx, 0, mHorizontalPaddingPx, 0);
final LinearLayout firstLineLayout = new LinearLayout(mContext);
firstLineLayout.setPadding(0, 0, 0, 0);
firstLineLayout.setOrientation(LinearLayout.HORIZONTAL);
@@ -104,6 +104,7 @@
lp.topMargin = h * 4 / 5;
mSecondLine.setLayoutParams(lp);
mFirstLine.setMinHeight(h);
+ mFirstLine.setPadding(mHorizontalPaddingPx, 0, 0, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index 2b071cc..cb685fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -373,6 +373,7 @@
public boolean activityOut;
public int overlayIconId;
public boolean filter;
+ public boolean isOverlayIconWide;
@Override
public boolean copyTo(State other) {
@@ -380,13 +381,15 @@
final boolean changed = o.enabled != enabled
|| o.connected != connected || o.activityIn != activityIn
|| o.activityOut != activityOut
- || o.overlayIconId != overlayIconId;
+ || o.overlayIconId != overlayIconId
+ || o.isOverlayIconWide != isOverlayIconWide;
o.enabled = enabled;
o.connected = connected;
o.activityIn = activityIn;
o.activityOut = activityOut;
o.overlayIconId = overlayIconId;
o.filter = filter;
+ o.isOverlayIconWide = isOverlayIconWide;
return super.copyTo(other) || changed;
}
@@ -399,6 +402,7 @@
rt.insert(rt.length() - 1, ",activityOut=" + activityOut);
rt.insert(rt.length() - 1, ",overlayIconId=" + overlayIconId);
rt.insert(rt.length() - 1, ",filter=" + filter);
+ rt.insert(rt.length() - 1, ",wideOverlayIcon=" + isOverlayIconWide);
return rt;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index e6175d2..8d7edb9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -230,7 +230,7 @@
final int w = MeasureSpec.getSize(widthMeasureSpec);
final int h = MeasureSpec.getSize(heightMeasureSpec);
final int iconSpec = exactly(mIconSizePx);
- mIcon.measure(iconSpec, iconSpec);
+ mIcon.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), iconSpec);
labelView().measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST));
if (mDual) {
mDivider.measure(widthMeasureSpec, exactly(mDivider.getLayoutParams().height));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 0ecdeaa..cfcd74e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -37,11 +37,16 @@
private ImageView mIn;
private ImageView mOut;
+ private int mWideOverlayIconStartPadding;
+
public SignalTileView(Context context) {
super(context);
mIn = addTrafficView(R.drawable.ic_qs_signal_in);
mOut = addTrafficView(R.drawable.ic_qs_signal_out);
+
+ mWideOverlayIconStartPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.wide_type_icon_start_padding_qs);
}
private ImageView addTrafficView(int icon) {
@@ -106,6 +111,11 @@
} else {
mOverlay.setVisibility(GONE);
}
+ if (s.overlayIconId > 0 && s.isOverlayIconWide) {
+ mSignal.setPaddingRelative(mWideOverlayIconStartPadding, 0, 0, 0);
+ } else {
+ mSignal.setPaddingRelative(0, 0, 0, 0);
+ }
Drawable drawable = mSignal.getDrawable();
if (state.autoMirrorDrawable && drawable != null) {
drawable.setAutoMirrored(true);
@@ -122,10 +132,9 @@
view.animate()
.setDuration(visible ? SHORT_DURATION : DEFAULT_DURATION)
.alpha(newAlpha)
- .withLayer()
.start();
} else {
view.setAlpha(newAlpha);
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 8743207..359a259 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -23,10 +23,8 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.qs.DataUsageGraph;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTileView;
import com.android.systemui.qs.SignalTileView;
@@ -34,8 +32,6 @@
import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
-import java.text.DecimalFormat;
-
/** Quick settings tile: Cellular **/
public class CellularTile extends QSTile<QSTile.SignalState> {
private static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
@@ -95,6 +91,7 @@
: !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
: cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
: R.drawable.ic_qs_signal_no_signal;
+ state.isOverlayIconWide = cb.isDataTypeIconWide;
state.autoMirrorDrawable = !cb.noSim;
state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiConnected
? cb.dataTypeIconId
@@ -142,6 +139,7 @@
boolean activityOut;
String enabledDesc;
boolean noSim;
+ boolean isDataTypeIconWide;
}
private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
@@ -162,7 +160,8 @@
int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim) {
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide) {
final CallbackInfo info = new CallbackInfo(); // TODO pool?
info.enabled = enabled;
info.wifiEnabled = mWifiEnabled;
@@ -176,6 +175,7 @@
info.activityOut = activityOut;
info.enabledDesc = description;
info.noSim = noSim;
+ info.isDataTypeIconWide = isDataTypeIconWide;
refreshState(info);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 46d8a9b..d1dc5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -60,7 +60,11 @@
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
final boolean locationEnabled = mController.isLocationEnabled();
- state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+
+ // Work around for bug 15916487: don't show location tile on top of lock screen. After the
+ // bug is fixed, this should be reverted to only hiding it on secure lock screens:
+ // state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+ state.visible = !mKeyguard.isShowing();
state.value = locationEnabled;
if (locationEnabled) {
state.iconId = R.drawable.ic_qs_location_on;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 4fc2ee4..0985812 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -206,7 +206,8 @@
int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim) {
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide) {
// noop
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 3e2ef94..34430d9 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -34,14 +34,12 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.android.systemui.R;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import java.util.ArrayList;
@@ -205,8 +203,7 @@
Drawable icon = getFullResIcon(td.resolveInfo, pm);
if (td.userId != UserHandle.myUserId()) {
// Need to badge the icon
- final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- icon = um.getBadgedDrawableForUser(icon, new UserHandle(td.userId));
+ icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(td.userId));
}
if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
+ td + ": " + thumbnail);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 2d114c0..787de4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -16,10 +16,12 @@
package com.android.systemui.recents;
+import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -137,7 +139,8 @@
// Notify recents to hide itself
Intent intent = new Intent(ACTION_HIDE_RECENTS_ACTIVITY);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, triggeredFromAltTab);
intent.putExtra(EXTRA_TRIGGERED_FROM_HOME_KEY, triggeredFromHomeKey);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
@@ -188,10 +191,14 @@
Task.TaskKey toTaskKey;
if (showNextTask) {
toTaskKey = group.getNextTaskInGroup(task);
- // XXX: We will actually set the appropriate launch animations here
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_next_affiliated_task_target,
+ R.anim.recents_launch_next_affiliated_task_source);
} else {
toTaskKey = group.getPrevTaskInGroup(task);
- // XXX: We will actually set the appropriate launch animations here
+ launchOpts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_prev_affiliated_task_target,
+ R.anim.recents_launch_prev_affiliated_task_source);
}
if (toTaskKey != null) {
toTask = stack.findTaskWithId(toTaskKey.id);
@@ -202,7 +209,11 @@
// Return early if there is no next task
if (toTask == null) {
- // XXX: We will actually show a bounce animation here
+ if (showNextTask) {
+ // XXX: Show the next-task bounce animation
+ } else {
+ // XXX: Show the prev-task bounce animation
+ }
return;
}
@@ -241,8 +252,8 @@
mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
mConfig.updateOnConfigurationChange();
mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
- mNavBarWidth, mTaskStackBounds);
- if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
+ (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), mTaskStackBounds);
+ if (mConfig.isLandscape && mConfig.hasTransposedNavBar) {
mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
} else {
mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
@@ -314,7 +325,8 @@
// Notify recents to toggle itself
Intent intent = new Intent(ACTION_TOGGLE_RECENTS_ACTIVITY);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
mLastToggleTime = System.currentTimeMillis();
return;
@@ -385,9 +397,9 @@
toTask);
if (toTransform != null && toTask.key != null) {
Rect toTaskRect = toTransform.rect;
-
- // XXX: Reduce the memory usage the to the task bar height
- Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+ int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale);
+ int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
+ Bitmap thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
Bitmap.Config.ARGB_8888);
if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
thumbnail.eraseColor(0xFFff0000);
@@ -401,7 +413,8 @@
mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
- thumbnail, toTaskRect.left, toTaskRect.top, this);
+ thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
+ toTaskRect.height(), this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -562,11 +575,35 @@
public void onAnimationStarted() {
// Notify recents to start the enter animation
if (!mStartAnimationTriggered) {
+ // There can be a race condition between the start animation callback and
+ // the start of the new activity (where we register the receiver that listens
+ // to this broadcast, so we add our own receiver and if that gets called, then
+ // we know the activity has not yet started and we can retry sending the broadcast.
+ BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (getResultCode() == Activity.RESULT_OK) {
+ mStartAnimationTriggered = true;
+ return;
+ }
+
+ // Schedule for the broadcast to be sent again after some time
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ onAnimationStarted();
+ }
+ }, 75);
+ }
+ };
+
+ // Send the broadcast to notify Recents that the animation has started
Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
- mStartAnimationTriggered = true;
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
+ Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+ fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 082dde6..8f92027 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -146,6 +146,9 @@
ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
+ // Notify the fallback receiver that we have successfully got the broadcast
+ // See AlternateRecentsComponent.onAnimationStarted()
+ setResultCode(Activity.RESULT_OK);
}
}
};
@@ -296,7 +299,7 @@
mSearchAppWidgetInfo);
Bundle opts = new Bundle();
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
// Set the padding to 0 for this search widget
mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 5d8181c..ed5c126 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -57,7 +57,8 @@
/** Layout */
boolean isLandscape;
- boolean transposeRecentsLayoutWithOrientation;
+ boolean hasTransposedSearchBar;
+ boolean hasTransposedNavBar;
/** Loading */
public int maxNumTasksToLoad;
@@ -74,8 +75,9 @@
public float taskStackOverscrollPct;
/** Task view animation and styles */
- public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeDelay;
+ public int taskViewEnterFromHomeDuration;
+ public int taskViewEnterFromHomeStaggerDelay;
public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
@@ -173,8 +175,8 @@
// Layout
isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
- transposeRecentsLayoutWithOrientation =
- res.getBoolean(R.bool.recents_transpose_layout_with_orientation);
+ hasTransposedSearchBar = res.getBoolean(R.bool.recents_has_transposed_search_bar);
+ hasTransposedNavBar = res.getBoolean(R.bool.recents_has_transposed_nav_bar);
// Insets
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
@@ -209,10 +211,12 @@
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
// Task view animation and styles
- taskViewEnterFromHomeDuration =
- res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
taskViewEnterFromHomeDelay =
res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+ taskViewEnterFromHomeDuration =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+ taskViewEnterFromHomeStaggerDelay =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
taskViewExitToHomeDuration =
res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
@@ -326,13 +330,12 @@
/** Returns whether the nav bar scrim should be visible. */
public boolean hasNavBarScrim() {
// Only show the scrim if we have recent tasks, and if the nav bar is not transposed
- return !launchedWithNoRecentTasks &&
- (!transposeRecentsLayoutWithOrientation || !isLandscape);
+ return !launchedWithNoRecentTasks && (!hasTransposedNavBar || !isLandscape);
}
/** Returns whether the current layout is horizontal. */
public boolean hasHorizontalLayout() {
- return isLandscape && transposeRecentsLayoutWithOrientation;
+ return isLandscape && hasTransposedSearchBar;
}
/**
@@ -343,7 +346,7 @@
Rect taskStackBounds) {
Rect searchBarBounds = new Rect();
getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds);
- if (isLandscape && transposeRecentsLayoutWithOrientation) {
+ if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left
taskStackBounds.set(searchBarBounds.right, topInset, windowWidth - rightInset, windowHeight);
} else {
@@ -364,7 +367,7 @@
searchBarSize = 0;
}
- if (isLandscape && transposeRecentsLayoutWithOrientation) {
+ if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left
searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index e27c0ac..bbd0a0d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -49,7 +49,6 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.util.Pair;
@@ -57,6 +56,7 @@
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import com.android.systemui.recents.Constants;
import java.io.IOException;
@@ -74,12 +74,12 @@
final static BitmapFactory.Options sBitmapOptions;
+ AccessibilityManager mAccm;
ActivityManager mAm;
IActivityManager mIam;
AppWidgetManager mAwm;
PackageManager mPm;
IPackageManager mIpm;
- UserManager mUm;
SearchManager mSm;
WindowManager mWm;
Display mDisplay;
@@ -99,11 +99,11 @@
/** Private constructor */
public SystemServicesProxy(Context context) {
+ mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManagerNative.getDefault();
mAwm = AppWidgetManager.getInstance(context);
mPm = context.getPackageManager();
- mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -343,7 +343,7 @@
* necessary.
*/
public Drawable getActivityIcon(ActivityInfo info, int userId) {
- if (mPm == null || mUm == null) return null;
+ if (mPm == null) return null;
// If we are mocking, then return a mock label
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
@@ -359,7 +359,7 @@
*/
public Drawable getBadgedIcon(Drawable icon, int userId) {
if (userId != UserHandle.myUserId()) {
- icon = mUm.getBadgedDrawableForUser(icon, new UserHandle(userId));
+ icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
}
return icon;
}
@@ -392,7 +392,7 @@
// Find the first Recents widget from the same package as the global assist activity
List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
- AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
for (AppWidgetProviderInfo info : widgets) {
if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
return info;
@@ -418,7 +418,7 @@
int searchWidgetId = host.allocateAppWidgetId();
Bundle opts = new Bundle();
opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
return null;
}
@@ -445,6 +445,15 @@
}
/**
+ * Returns whether touch exploration is currently enabled.
+ */
+ public boolean isTouchExplorationEnabled() {
+ if (mAccm == null) return false;
+
+ return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled();
+ }
+
+ /**
* Returns a global setting.
*/
public int getGlobalSetting(Context context, String setting) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 0c6e7b6..1bfb41f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -413,10 +413,8 @@
final SystemServicesProxy ssp =
RecentsTaskLoader.getInstance().getSystemServicesProxy();
ActivityOptions opts = null;
- int thumbnailWidth = transform.rect.width();
- int thumbnailHeight = transform.rect.height();
- if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
- task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
+ if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+ task.thumbnail.getHeight() > 0) {
Bitmap b;
if (tv != null) {
// Disable any focused state before we draw the header
@@ -424,7 +422,11 @@
tv.unsetFocusedTask();
}
- b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+ float scale = tv.getScaleX();
+ int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+ int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+ b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+ Bitmap.Config.ARGB_8888);
if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
b.eraseColor(0xFFff0000);
} else {
@@ -435,7 +437,7 @@
}
} else {
// Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
- b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+ b = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
}
ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
@@ -456,7 +458,8 @@
};
}
opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
- b, offsetX, offsetY, animStartedListener);
+ b, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
+ animStartedListener);
}
final ActivityOptions launchOpts = opts;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index dbed136..895b9d1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -22,11 +22,15 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -67,6 +71,7 @@
DebugOverlayView mDebugOverlay;
Rect mTaskStackBounds = new Rect();
int mFocusedTaskIndex = -1;
+ int mPrevAccessibilityFocusedIndex = -1;
// Optimizations
int mStackViewsAnimationDuration;
@@ -244,6 +249,9 @@
/** Synchronizes the views with the model */
boolean synchronizeStackViewsWithModel() {
if (mStackViewsDirty) {
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ SystemServicesProxy ssp = loader.getSystemServicesProxy();
+
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
float stackScroll = mStackScroller.getStackScroll();
@@ -293,6 +301,18 @@
// Animate the task into place
tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration);
+
+ // Request accessibility focus on the next view if we removed the task
+ // that previously held accessibility focus
+ childCount = getChildCount();
+ if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
+ TaskView atv = (TaskView) getChildAt(childCount - 1);
+ int indexOfTask = mStack.indexOfTask(atv.getTask());
+ if (mPrevAccessibilityFocusedIndex != indexOfTask) {
+ tv.requestAccessibilityFocus();
+ mPrevAccessibilityFocusedIndex = indexOfTask;
+ }
+ }
}
// Reset the request-synchronize params
@@ -432,6 +452,22 @@
}
@Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ int childCount = getChildCount();
+ if (childCount > 0) {
+ TaskView backMostTask = (TaskView) getChildAt(0);
+ TaskView frontMostTask = (TaskView) getChildAt(childCount - 1);
+ event.setFromIndex(mStack.indexOfTask(backMostTask.getTask()));
+ event.setToIndex(mStack.indexOfTask(frontMostTask.getTask()));
+ event.setContentDescription(frontMostTask.getTask().activityLabel);
+ }
+ event.setItemCount(mStack.getTaskCount());
+ event.setScrollY(mStackScroller.mScroller.getCurrY());
+ event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mTouchHandler.onInterceptTouchEvent(ev);
}
@@ -447,6 +483,8 @@
// Synchronize the views
synchronizeStackViewsWithModel();
clipTaskViews();
+ // Notify accessibility
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
}
/** Computes the stack and task rects */
@@ -623,6 +661,15 @@
mStartEnterAnimationCompleted = true;
// Start dozing
mUIDozeTrigger.startDozing();
+ // Focus the first view if accessibility is enabled
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ SystemServicesProxy ssp = loader.getSystemServicesProxy();
+ int childCount = getChildCount();
+ if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
+ TaskView tv = ((TaskView) getChildAt(childCount - 1));
+ tv.requestAccessibilityFocus();
+ mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
+ }
}
});
}
@@ -812,6 +859,11 @@
public void prepareViewToEnterPool(TaskView tv) {
Task task = tv.getTask();
+ // Clear the accessibility focus for that view
+ if (tv.isAccessibilityFocused()) {
+ tv.clearAccessibilityFocus();
+ }
+
// Report that this tasks's data is no longer being used
RecentsTaskLoader.getInstance().unloadTaskData(task);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index eecc170..4563597 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -284,7 +284,7 @@
float scaledWindowInsetTop = (int) (taskScale * windowInsetTop);
float scaledTranslationY = taskRect.top + transform.translationY -
(scaledWindowInsetTop + scaledYOffset);
- startDelay = mConfig.taskViewEnterFromHomeDelay;
+ startDelay = mConfig.taskViewEnterFromHomeStaggerDelay;
// Animate the top clip
mViewBounds.animateClipTop(windowInsetTop, duration,
@@ -410,8 +410,8 @@
} else if (mConfig.launchedFromHome) {
// Animate the tasks up
int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
- int delay = mConfig.taskBarEnterAnimDelay +
- frontIndex * mConfig.taskViewEnterFromHomeDelay;
+ int delay = mConfig.taskViewEnterFromHomeDelay +
+ frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
if (Constants.DebugFlags.App.EnableShadows) {
animate().translationZ(transform.translationZ);
}
@@ -839,25 +839,28 @@
@Override
public void onClick(final View v) {
- // We purposely post the handler delayed to allow for the touch feedback to draw
final TaskView tv = this;
- postDelayed(new Runnable() {
- @Override
- public void run() {
- if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
- mCb.onTaskViewAppIconClicked(tv);
- } else if (v == mHeaderView.mDismissButton) {
- dismissTask();
- } else {
- if (v == mActionButtonView) {
- // Reset the translation of the action button before we animate it out
- mActionButtonView.setTranslationZ(0f);
+ final boolean delayViewClick = (v != this) && (v != mActionButtonView);
+ if (delayViewClick) {
+ // We purposely post the handler delayed to allow for the touch feedback to draw
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
+ mCb.onTaskViewAppIconClicked(tv);
+ } else if (v == mHeaderView.mDismissButton) {
+ dismissTask();
}
- mCb.onTaskViewClicked(tv, tv.getTask(),
- (v == mFooterView || v == mActionButtonView));
}
+ }, 125);
+ } else {
+ if (v == mActionButtonView) {
+ // Reset the translation of the action button before we animate it out
+ mActionButtonView.setTranslationZ(0f);
}
- }, 125);
+ mCb.onTaskViewClicked(tv, tv.getTask(),
+ (v == mFooterView || v == mActionButtonView));
+ }
}
/**** View.OnLongClickListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index e6984b2..c869ba4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -121,7 +121,6 @@
private NotificationBackgroundView mBackgroundNormal;
private NotificationBackgroundView mBackgroundDimmed;
- private NotificationScrimView mScrimView;
private ObjectAnimator mBackgroundAnimator;
private RectF mAppearAnimationRect = new RectF();
private PorterDuffColorFilter mAppearAnimationFilter;
@@ -173,8 +172,6 @@
mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
updateBackground();
updateBackgroundTint();
- mScrimView = (NotificationScrimView) findViewById(R.id.scrim_view);
- setScrimAmount(0);
}
private final Runnable mTapTimeoutRunnable = new Runnable() {
@@ -465,7 +462,6 @@
setPivotY(actualHeight / 2);
mBackgroundNormal.setActualHeight(actualHeight);
mBackgroundDimmed.setActualHeight(actualHeight);
- mScrimView.setActualHeight(actualHeight);
}
@Override
@@ -473,7 +469,6 @@
super.setClipTopAmount(clipTopAmount);
mBackgroundNormal.setClipTopAmount(clipTopAmount);
mBackgroundDimmed.setClipTopAmount(clipTopAmount);
- mScrimView.setClipTopAmount(clipTopAmount);
}
@Override
@@ -496,11 +491,6 @@
}
}
- @Override
- public void setScrimAmount(float scrimAmount) {
- mScrimView.setAlpha(scrimAmount);
- }
-
private void startAppearAnimation(boolean isAppearing, float translationDirection, long delay,
long duration, final Runnable onFinishedRunnable) {
if (mAppearAnimator != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2c1d70d..4d85352 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -39,6 +39,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
@@ -70,6 +71,7 @@
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.widget.DateTimeView;
import android.widget.ImageView;
@@ -91,6 +93,7 @@
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
+import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -159,6 +162,7 @@
final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
protected int mLayoutDirection = -1; // invalid
+ protected AccessibilityManager mAccessibilityManager;
private Locale mLocale;
private float mFontScale;
@@ -260,10 +264,12 @@
final boolean isActivity = pendingIntent.isActivity();
if (isActivity) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+ final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, pendingIntent.getIntent(), mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
public boolean onDismiss() {
- if (keyguardShowing) {
+ if (keyguardShowing && !afterKeyguardGone) {
try {
ActivityManagerNative.getDefault()
.keyguardWaitingForActivityDrawn();
@@ -277,7 +283,7 @@
}
boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
- overrideActivityPendingAppTransition(keyguardShowing);
+ overrideActivityPendingAppTransition(keyguardShowing && !afterKeyguardGone);
// close the shade if it was open
if (handled) {
@@ -287,7 +293,7 @@
// Wait for activity start.
return handled;
}
- }, false /* afterKeyguardGone */);
+ }, afterKeyguardGone);
return true;
} else {
return super.onClickHandler(view, pendingIntent, fillInIntent);
@@ -438,6 +444,9 @@
mNotificationData = new NotificationData(this);
+ mAccessibilityManager = (AccessibilityManager)
+ mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
mDreamManager = IDreamManager.Stub.asInterface(
ServiceManager.checkService(DreamService.DREAM_SERVICE));
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
@@ -558,6 +567,8 @@
// disable lockscreen notifications until user acts on the banner.
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
final String packageName = mContext.getPackageName();
PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
@@ -676,19 +687,11 @@
protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
NotificationData.Entry entry) {
- PackageManager pmUser = getPackageManagerForUser(
- entry.notification.getUser().getIdentifier());
- int version = 0;
- try {
- ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
- version = info.targetSdkVersion;
- } catch (NameNotFoundException ex) {
- Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
- }
if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
// Using custom RemoteViews
- if (version >= Build.VERSION_CODES.GINGERBREAD && version < Build.VERSION_CODES.L) {
+ if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
+ && entry.targetSdk < Build.VERSION_CODES.L) {
entry.row.setShowingLegacyBackground(true);
entry.legacy = true;
}
@@ -704,7 +707,7 @@
}
if (entry.icon != null) {
- if (version >= Build.VERSION_CODES.L) {
+ if (entry.targetSdk >= Build.VERSION_CODES.L) {
entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
} else {
entry.icon.setColorFilter(null);
@@ -1317,6 +1320,14 @@
}
}
+ // Extract target SDK version.
+ try {
+ ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
+ entry.targetSdk = info.targetSdkVersion;
+ } catch (NameNotFoundException ex) {
+ Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+ }
+
if (publicViewLocal == null) {
// Add a basic notification template
publicViewLocal = LayoutInflater.from(mContext).inflate(
@@ -1347,17 +1358,22 @@
Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
icon.setImageDrawable(iconDrawable);
- if (mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
+ if (entry.targetSdk >= Build.VERSION_CODES.L
+ || mNotificationColorUtil.isGrayscaleIcon(iconDrawable)) {
icon.setBackgroundResource(
com.android.internal.R.drawable.notification_icon_legacy_bg);
int padding = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_large_icon_circle_padding);
icon.setPadding(padding, padding, padding, padding);
+ if (sbn.getNotification().color != Notification.COLOR_DEFAULT) {
+ icon.getBackground().setColorFilter(
+ sbn.getNotification().color, PorterDuff.Mode.SRC_ATOP);
+ }
}
if (profileBadge != null) {
- Drawable profileDrawable
- = mUserManager.getBadgeForUser(entry.notification.getUser(), 0);
+ Drawable profileDrawable = mContext.getPackageManager().getUserBadgeForDensity(
+ entry.notification.getUser(), 0);
if (profileDrawable != null) {
profileBadge.setImageDrawable(profileDrawable);
profileBadge.setVisibility(View.VISIBLE);
@@ -1438,6 +1454,9 @@
public void onClick(final View v) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+ final boolean afterKeyguardGone = mIntent.isActivity()
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
+ mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
public boolean onDismiss() {
if (mIsHeadsUp) {
@@ -1446,7 +1465,7 @@
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- if (keyguardShowing) {
+ if (keyguardShowing && !afterKeyguardGone) {
try {
ActivityManagerNative.getDefault()
.keyguardWaitingForActivityDrawn();
@@ -1470,7 +1489,8 @@
// TODO: Dismiss Keyguard.
}
if (mIntent.isActivity()) {
- overrideActivityPendingAppTransition(keyguardShowing);
+ overrideActivityPendingAppTransition(keyguardShowing
+ && !afterKeyguardGone);
}
}
@@ -1488,7 +1508,7 @@
return mIntent != null && mIntent.isActivity();
}
- }, false /* afterKeyguardGone */);
+ }, afterKeyguardGone);
}
}
@@ -1623,10 +1643,11 @@
}
}
boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
- if (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
- || !showOnKeyguard)) {
+ if ((isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
+ (onKeyguard && (visibleNotifications >= maxKeyguardNotifications
+ || !showOnKeyguard))) {
entry.row.setVisibility(View.GONE);
- if (showOnKeyguard) {
+ if (onKeyguard && showOnKeyguard) {
mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
}
} else {
@@ -1773,7 +1794,7 @@
oldEntry.notification.getNotification().tickerText);
final boolean shouldInterrupt = shouldInterrupt(notification);
- final boolean alertAgain = alertAgain(oldEntry);
+ final boolean alertAgain = alertAgain(oldEntry, n);
boolean updateSuccessful = false;
if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged
&& publicUnchanged) {
@@ -1908,9 +1929,6 @@
: null;
// Reapply the RemoteViews
- if (entry.row != null) {
- entry.row.resetHeight();
- }
contentView.reapply(mContext, entry.expanded, mOnClickHandler);
if (bigContentView != null && entry.getBigContentView() != null) {
bigContentView.reapply(mContext, entry.getBigContentView(),
@@ -1929,6 +1947,7 @@
entry.row.setOnClickListener(null);
}
entry.row.notifyContentUpdated();
+ entry.row.resetHeight();
}
protected void notifyHeadsUpScreenOn(boolean screenOn) {
@@ -1937,10 +1956,9 @@
}
}
- private boolean alertAgain(Entry entry) {
- final StatusBarNotification sbn = entry.notification;
- return entry == null || !entry.hasInterrupted()
- || (sbn.getNotification().flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+ private boolean alertAgain(Entry oldEntry, Notification newNotification) {
+ return oldEntry == null || !oldEntry.hasInterrupted()
+ || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
}
protected boolean shouldInterrupt(StatusBarNotification sbn) {
@@ -1962,10 +1980,13 @@
boolean hasTicker = mHeadsUpTicker && !TextUtils.isEmpty(notification.tickerText);
boolean isAllowed = notification.extras.getInt(Notification.EXTRA_AS_HEADS_UP,
Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER;
+ boolean accessibilityForcesLaunch = isFullscreen
+ && mAccessibilityManager.isTouchExplorationEnabled();
final KeyguardTouchDelegate keyguard = KeyguardTouchDelegate.getInstance(mContext);
boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
&& isAllowed
+ && !accessibilityForcesLaunch
&& mPowerManager.isScreenOn()
&& !keyguard.isShowingAndNotOccluded()
&& !keyguard.isInputRestricted();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index e3a0b18..c13593a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -147,6 +147,7 @@
mMaxExpandHeight = 0;
mWasReset = true;
onHeightReset();
+ requestLayout();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 2838747..c8f756e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -255,8 +255,6 @@
public abstract void performAddAnimation(long delay, long duration);
- public abstract void setScrimAmount(float scrimAmount);
-
public void setBelowSpeedBump(boolean below) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index cef889c..34c458a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.app.Notification;
+import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
@@ -47,6 +48,7 @@
private boolean interruption;
public boolean autoRedacted; // whether the redacted notification was generated by us
public boolean legacy; // whether the notification has a legacy, dark background
+ public int targetSdk;
public Entry(StatusBarNotification n, StatusBarIconView ic) {
this.key = n.getKey();
@@ -99,15 +101,26 @@
@Override
public int compare(Entry a, Entry b) {
- String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
-
// Upsort current media notification.
+ String mediaNotification = mEnvironment.getCurrentMediaNotificationKey();
boolean aMedia = a.key.equals(mediaNotification);
boolean bMedia = b.key.equals(mediaNotification);
if (aMedia != bMedia) {
return aMedia ? -1 : 1;
}
+ final StatusBarNotification na = a.notification;
+ final StatusBarNotification nb = b.notification;
+
+ // Upsort PRIORITY_MAX system notifications
+ boolean aSystemMax = na.getNotification().priority >= Notification.PRIORITY_MAX &&
+ isSystemNotification(na);
+ boolean bSystemMax = nb.getNotification().priority >= Notification.PRIORITY_MAX &&
+ isSystemNotification(nb);
+ if (aSystemMax != bSystemMax) {
+ return aSystemMax ? -1 : 1;
+ }
+
// RankingMap as received from NoMan.
if (mRankingMap != null) {
mRankingMap.getRanking(a.key, mRankingA);
@@ -115,8 +128,6 @@
return mRankingA.getRank() - mRankingB.getRank();
}
- final StatusBarNotification na = a.notification;
- final StatusBarNotification nb = b.notification;
int d = nb.getScore() - na.getScore();
if (a.interruption != b.interruption) {
return a.interruption ? -1 : 1;
@@ -173,6 +184,14 @@
return false;
}
+ public int getVisibilityOverride(String key) {
+ if (mRankingMap != null) {
+ mRankingMap.getRanking(key, mTmpRanking);
+ return mTmpRanking.getVisibilityOverride();
+ }
+ return NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ }
+
private void updateRankingAndSort(RankingMap ranking) {
if (ranking != null) {
mRankingMap = ranking;
@@ -296,11 +315,16 @@
pw.println(" tickerText=\"" + n.getNotification().tickerText + "\"");
}
+ private static boolean isSystemNotification(StatusBarNotification sbn) {
+ String sbnPackage = sbn.getPackageName();
+ return "android".equals(sbnPackage) || "com.android.systemui".equals(sbnPackage);
+ }
+
/**
* Provides access to keyguard state and user settings dependent data.
*/
public interface Environment {
- public boolean shouldHideSensitiveContents(int userId);
+ public boolean shouldHideSensitiveContents(int userid);
public boolean isDeviceProvisioned();
public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
public String getCurrentMediaNotificationKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
deleted file mode 100644
index 440b2c1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationScrimView.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2014 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.systemui.statusbar;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.android.keyguard.R;
-
-/**
- * A view that can be used for both the dimmed and normal background of an notification.
- */
-public class NotificationScrimView extends View {
-
- private Drawable mBackground;
- private int mClipTopAmount;
- private int mActualHeight;
-
- public NotificationScrimView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mBackground = getResources().getDrawable(R.drawable.notification_scrim);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- draw(canvas, mBackground);
- }
-
- private void draw(Canvas canvas, Drawable drawable) {
- if (drawable != null) {
- drawable.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
- drawable.draw(canvas);
- }
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return super.verifyDrawable(who) || who == mBackground;
- }
-
- public void setActualHeight(int actualHeight) {
- mActualHeight = actualHeight;
- invalidate();
- }
-
- public int getActualHeight() {
- return mActualHeight;
- }
-
- public void setClipTopAmount(int clipTopAmount) {
- mClipTopAmount = clipTopAmount;
- invalidate();
- }
-
- @Override
- public boolean hasOverlappingRendering() {
-
- // Prevents this view from creating a layer when alpha is animating.
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 5883c26..18ef024 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -27,17 +27,21 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
// Intimately tied to the design of res/layout/signal_cluster_view.xml
public class SignalClusterView
extends LinearLayout
- implements NetworkControllerImpl.SignalCluster {
+ implements NetworkControllerImpl.SignalCluster,
+ SecurityController.SecurityControllerCallback {
static final String TAG = "SignalClusterView";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
NetworkControllerImpl mNC;
+ SecurityController mSC;
+ private boolean mVpnVisible = false;
private boolean mWifiVisible = false;
private int mWifiStrengthId = 0;
private boolean mMobileVisible = false;
@@ -46,10 +50,14 @@
private int mAirplaneIconId = 0;
private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
private boolean mRoaming;
+ private boolean mIsMobileTypeIconWide;
ViewGroup mWifiGroup, mMobileGroup;
- ImageView mWifi, mMobile, mMobileType, mAirplane;
+ ImageView mVpn, mWifi, mMobile, mMobileType, mAirplane;
View mWifiAirplaneSpacer;
+ View mWifiSignalSpacer;
+
+ private int mWideTypeIconStartPadding;
public SignalClusterView(Context context) {
this(context, null);
@@ -68,10 +76,25 @@
mNC = nc;
}
+ public void setSecurityController(SecurityController sc) {
+ if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
+ mSC = sc;
+ mSC.addCallback(this);
+ mVpnVisible = mSC.isVpnEnabled();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize(
+ R.dimen.wide_type_icon_start_padding);
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ mVpn = (ImageView) findViewById(R.id.vpn);
mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
mWifi = (ImageView) findViewById(R.id.wifi_signal);
mMobileGroup = (ViewGroup) findViewById(R.id.mobile_combo);
@@ -79,12 +102,14 @@
mMobileType = (ImageView) findViewById(R.id.mobile_type);
mAirplane = (ImageView) findViewById(R.id.airplane);
mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
+ mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer);
apply();
}
@Override
protected void onDetachedFromWindow() {
+ mVpn = null;
mWifiGroup = null;
mWifi = null;
mMobileGroup = null;
@@ -95,6 +120,18 @@
super.onDetachedFromWindow();
}
+ // From SecurityController.
+ @Override
+ public void onStateChanged() {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mVpnVisible = mSC.isVpnEnabled();
+ apply();
+ }
+ });
+ }
+
@Override
public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) {
mWifiVisible = visible;
@@ -106,13 +143,15 @@
@Override
public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming) {
+ String contentDescription, String typeContentDescription, boolean roaming,
+ boolean isTypeIconWide) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon;
mMobileTypeId = typeIcon;
mMobileDescription = contentDescription;
mMobileTypeDescription = typeContentDescription;
mRoaming = roaming;
+ mIsMobileTypeIconWide = isTypeIconWide;
apply();
}
@@ -168,6 +207,8 @@
private void apply() {
if (mWifiGroup == null) return;
+ mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
+ if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
if (mWifiVisible) {
mWifi.setImageResource(mWifiStrengthId);
mWifiGroup.setContentDescription(mWifiDescription);
@@ -203,6 +244,14 @@
mWifiAirplaneSpacer.setVisibility(View.GONE);
}
+ if (mRoaming && mMobileVisible && mWifiVisible) {
+ mWifiSignalSpacer.setVisibility(View.VISIBLE);
+ } else {
+ mWifiSignalSpacer.setVisibility(View.GONE);
+ }
+
+ mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0);
+
if (DEBUG) Log.d(TAG,
String.format("mobile: %s sig=%d typ=%d",
(mMobileVisible ? "VISIBLE" : "GONE"),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index 816612b..1fc8744 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -126,9 +126,4 @@
// TODO: Use duration
performVisibilityAnimation(true, delay);
}
-
- @Override
- public void setScrimAmount(float scrimAmount) {
- // We don't need to scrim the speedbumps
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
index 62a492e..64d80cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StackScrollerDecorView.java
@@ -90,7 +90,6 @@
.alpha(endValue)
.setInterpolator(interpolator)
.setDuration(260)
- .withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -127,11 +126,6 @@
}
@Override
- public void setScrimAmount(float scrimAmount) {
- // We don't need to scrim the dismissView
- }
-
- @Override
public boolean hasOverlappingRendering() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index 9dfbb27..23810f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,5 +24,5 @@
* Keyguard.
*/
public interface ActivityStarter {
- public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone);
+ public void startActivity(Intent intent, boolean dismissShade);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index f9da30f..e84ca52 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -315,15 +315,15 @@
public void launchCamera() {
mFlashlightController.killFlashlight();
Intent intent = getCameraIntent();
- boolean wouldLaunchResolverActivity = mPreviewInflater.wouldLaunchResolverActivity(intent);
+ boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, intent, mLockPatternUtils.getCurrentUser());
if (intent == SECURE_CAMERA_INTENT && !wouldLaunchResolverActivity) {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
} else {
// We need to delay starting the activity because ResolverActivity finishes itself if
// launched behind lockscreen.
- mActivityStarter.startActivity(intent, false /* dismissShade */,
- wouldLaunchResolverActivity /* afterKeyguardGone */);
+ mActivityStarter.startActivity(intent, false /* dismissShade */);
}
}
@@ -337,8 +337,7 @@
}
});
} else {
- mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */,
- mPreviewInflater.wouldLaunchResolverActivity(PHONE_INTENT));
+ mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index d7144da..685c184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,6 +30,7 @@
import com.android.systemui.R;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* Container for image of the multi user switcher (tappable).
@@ -73,8 +74,10 @@
mKeyguardUserSwitcher.show(true /* animate */);
}
} else {
- mQsPanel.showDetailAdapter(true,
- mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
+ if (mQsPanel != null) {
+ mQsPanel.showDetailAdapter(true,
+ mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
+ }
}
} else {
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
@@ -90,9 +93,24 @@
if (isClickable()) {
final UserManager um = UserManager.get(getContext());
- String text = mContext.getString(um.isUserSwitcherEnabled()
- ? R.string.accessibility_multi_user_switch_switcher
- : R.string.accessibility_multi_user_switch_quick_contact);
+ String text;
+ if (um.isUserSwitcherEnabled()) {
+ String currentUser = null;
+ if (mQsPanel != null) {
+ UserSwitcherController controller = mQsPanel.getHost()
+ .getUserSwitcherController();
+ currentUser = controller.getCurrentUserName(mContext);
+ }
+ if (TextUtils.isEmpty(currentUser)) {
+ text = mContext.getString(R.string.accessibility_multi_user_switch_switcher);
+ } else {
+ text = mContext.getString(
+ R.string.accessibility_multi_user_switch_switcher_with_current,
+ currentUser);
+ }
+ } else {
+ text = mContext.getString(R.string.accessibility_multi_user_switch_quick_contact);
+ }
if (!TextUtils.isEmpty(text)) {
event.getText().add(text);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index b633453..79bb1cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -31,7 +31,6 @@
private final GestureDetector mTaskSwitcherDetector;
private final int mScrollTouchSlop;
private final int mMinFlingVelocity;
- private boolean mInterceptTouches;
private int mTouchDownX;
private int mTouchDownY;
@@ -56,11 +55,11 @@
// task switcher detector
mTaskSwitcherDetector.onTouchEvent(event);
int action = event.getAction();
+ boolean interceptTouches = false;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mTouchDownX = (int) event.getX();
mTouchDownY = (int) event.getY();
- mInterceptTouches = false;
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -72,21 +71,19 @@
? xDiff > mScrollTouchSlop && xDiff > yDiff
: yDiff > mScrollTouchSlop && yDiff > xDiff;
if (exceededTouchSlop) {
- mInterceptTouches = true;
+ interceptTouches = true;
return true;
}
break;
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
- mInterceptTouches = false;
break;
}
- return mInterceptTouches;
+ return interceptTouches;
}
public boolean onTouchEvent(MotionEvent event) {
- if (!mInterceptTouches) return false;
return mTaskSwitcherDetector.onTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index bae1864..9585e17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -23,6 +23,8 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.MotionEvent;
@@ -60,6 +62,10 @@
private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
+ private static final int DOZE_BACKGROUND_COLOR = 0xff000000;
+ private static final int TAG_KEY_ANIM = R.id.scrim;
+ private static final long DOZE_BACKGROUND_ANIM_DURATION = ScrimController.ANIMATION_DURATION;
+
private KeyguardAffordanceHelper mAfforanceHelper;
private StatusBarHeaderView mHeader;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -559,7 +565,7 @@
}
private boolean isBelowFalsingThreshold() {
- return !mQsTouchAboveFalsingThreshold && mStatusBar.isFalsingThresholdNeeded();
+ return !mQsTouchAboveFalsingThreshold && mStatusBarState == StatusBarState.KEYGUARD;
}
private float getQsExpansionFraction() {
@@ -1047,7 +1053,6 @@
int startDistance = mQsMinExpansionHeight + mNotificationScrimWaitDistance;
float progress = (height - startDistance) / (mQsMaxExpansionHeight - startDistance);
progress = Math.max(0.0f, Math.min(progress, 1.0f));
- mNotificationStackScroller.setScrimAlpha(progress);
}
private float getHeaderExpansionFraction() {
@@ -1279,7 +1284,7 @@
private void updateNotificationTranslucency() {
float alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight())
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
- + mNotificationStackScroller.getCollapseSecondCardPadding());
+ - mNotificationStackScroller.getCollapseSecondCardPadding());
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) {
@@ -1725,13 +1730,58 @@
if (dozing == mDozing) return;
mDozing = dozing;
if (mDozing) {
- setBackgroundColor(0xff000000);
+ setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0xff, false /*animate*/);
} else {
- setBackground(null);
+ setBackgroundColorAlpha(this, DOZE_BACKGROUND_COLOR, 0, true /*animate*/);
}
updateKeyguardStatusBarVisibility();
}
+ private static void setBackgroundColorAlpha(final View target, int rgb, int targetAlpha,
+ boolean animate) {
+ int currentAlpha = getBackgroundAlpha(target);
+ if (currentAlpha == targetAlpha) {
+ return;
+ }
+ final int r = Color.red(rgb);
+ final int g = Color.green(rgb);
+ final int b = Color.blue(rgb);
+ Object runningAnim = target.getTag(TAG_KEY_ANIM);
+ if (runningAnim instanceof ValueAnimator) {
+ ((ValueAnimator) runningAnim).cancel();
+ }
+ if (!animate) {
+ target.setBackgroundColor(Color.argb(targetAlpha, r, g, b));
+ return;
+ }
+ ValueAnimator anim = ValueAnimator.ofInt(currentAlpha, targetAlpha);
+ anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int value = (int) animation.getAnimatedValue();
+ target.setBackgroundColor(Color.argb(value, r, g, b));
+ }
+ });
+ anim.setDuration(DOZE_BACKGROUND_ANIM_DURATION);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ target.setTag(TAG_KEY_ANIM, null);
+ }
+ });
+ anim.start();
+ target.setTag(TAG_KEY_ANIM, anim);
+ }
+
+ private static int getBackgroundAlpha(View view) {
+ if (view.getBackground() instanceof ColorDrawable) {
+ ColorDrawable drawable = (ColorDrawable) view.getBackground();
+ return Color.alpha(drawable.getColor());
+ } else {
+ return 0;
+ }
+ }
+
public void setShadeEmpty(boolean shadeEmpty) {
mShadeEmpty = shadeEmpty;
updateEmptyShadeView();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 00e9790..5d4c831 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -71,6 +71,7 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
@@ -148,6 +149,7 @@
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.SecurityControllerImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -785,8 +787,11 @@
mNetworkController.addSignalCluster(signalCluster);
mNetworkController.addSignalCluster(signalClusterKeyguard);
mNetworkController.addSignalCluster(signalClusterQs);
+ signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
+ signalClusterKeyguard.setSecurityController(mSecurityController);
signalClusterKeyguard.setNetworkController(mNetworkController);
+ signalClusterQs.setSecurityController(mSecurityController);
signalClusterQs.setNetworkController(mNetworkController);
final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
if (isAPhone) {
@@ -1077,7 +1082,6 @@
};
private long mLastLockToAppLongPress;
- private AccessibilityManager mAccessibilityManager;
private View.OnLongClickListener mLongPressBackRecentsListener =
new View.OnLongClickListener() {
@Override
@@ -1414,11 +1418,12 @@
// Display public version of the notification if we need to redact.
final boolean hideSensitive =
!userAllowsPrivateNotificationsInPublic(ent.notification.getUserId());
- boolean sensitive = vis == Notification.VISIBILITY_PRIVATE;
- boolean showingPublic = sensitive && hideSensitive && isLockscreenPublicMode();
- ent.row.setSensitive(sensitive && hideSensitive);
+ boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
+ boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
+ boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
+ boolean showingPublic = sensitive && isLockscreenPublicMode();
+ ent.row.setSensitive(sensitive);
if (ent.autoRedacted && ent.legacy) {
-
// TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
// for legacy auto redacted notifications.
if (showingPublic) {
@@ -1479,6 +1484,11 @@
mShadeUpdates.check();
}
+ private boolean packageHasVisibilityOverride(String key) {
+ return mNotificationData.getVisibilityOverride(key)
+ != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ }
+
private void updateClearAll() {
boolean showDismissView =
mState != StatusBarState.KEYGUARD &&
@@ -1552,8 +1562,9 @@
}
}
- for (View remove : toRemove) {
- mNotificationIcons.removeView(remove);
+ final int toRemoveCount = toRemove.size();
+ for (int i = 0; i < toRemoveCount; i++) {
+ mNotificationIcons.removeView(toRemove.get(i));
}
for (int i=0; i<toShow.size(); i++) {
@@ -1562,6 +1573,18 @@
mNotificationIcons.addView(v, i, params);
}
}
+
+ // Resort notification icons
+ final int childCount = mNotificationIcons.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View actual = mNotificationIcons.getChildAt(i);
+ StatusBarIconView expected = toShow.get(i);
+ if (actual == expected) {
+ continue;
+ }
+ mNotificationIcons.removeView(expected);
+ mNotificationIcons.addView(expected, i);
+ }
}
@Override
@@ -1723,12 +1746,12 @@
// something old was playing
Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
+ mMediaController);
- mMediaController.removeCallback(mMediaListener);
+ mMediaController.unregisterCallback(mMediaListener);
}
mMediaController = controller;
if (mMediaController != null) {
- mMediaController.addCallback(mMediaListener);
+ mMediaController.registerCallback(mMediaListener);
mMediaMetadata = mMediaController.getMetadata();
if (DEBUG_MEDIA) {
Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: "
@@ -2047,8 +2070,8 @@
}
@Override
- public void startActivity(Intent intent, boolean dismissShade, boolean afterKeyguardGone) {
- startActivityDismissingKeyguard(intent, false, dismissShade, afterKeyguardGone);
+ public void startActivity(Intent intent, boolean dismissShade) {
+ startActivityDismissingKeyguard(intent, false, dismissShade);
}
public ScrimController getScrimController() {
@@ -2937,9 +2960,11 @@
}
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
- final boolean dismissShade, final boolean afterKeyguardGone) {
+ final boolean dismissShade) {
if (onlyProvisioned && !isDeviceProvisioned()) return;
+ final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+ mContext, intent, mCurrentUserId);
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
@@ -3288,8 +3313,7 @@
}
private void handleStartSettingsActivity(Intent intent, boolean onlyProvisioned) {
- startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */,
- false /* afterKeyguardGone */);
+ startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
}
private static class FastColorDrawable extends Drawable {
@@ -3767,7 +3791,9 @@
row = (ExpandableNotificationRow) expandView;
row.setUserExpanded(true);
}
- if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) {
+ boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
+ || !mShowLockscreenNotifications;
+ if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
mLeaveOpenOnKeyguardHide = true;
showBouncer();
mDraggedDownRow = row;
@@ -3847,10 +3873,6 @@
try {
boolean sendBackLongPress = false;
IActivityManager activityManager = ActivityManagerNative.getDefault();
- if (mAccessibilityManager == null) {
- mAccessibilityManager = (AccessibilityManager)
- mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- }
boolean isAccessiblityEnabled = mAccessibilityManager.isEnabled();
if (activityManager.isInLockTaskMode() && !isAccessiblityEnabled) {
long time = System.currentTimeMillis();
@@ -3926,6 +3948,13 @@
return !mNotificationData.getActiveNotifications().isEmpty();
}
+ public void wakeUpIfDozing(long time) {
+ if (mDozeServiceHost != null && mDozeServiceHost.isDozing()) {
+ PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ pm.wakeUp(time);
+ }
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
@@ -3970,6 +3999,10 @@
+ mCurrentDozeService + "]";
}
+ public boolean isDozing() {
+ return mCurrentDozeService != null;
+ }
+
public void firePowerSaveChanged(boolean active) {
for (Callback callback : mCallbacks) {
callback.onPowerSaveChanged(active);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 455c336..be48df7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -38,11 +38,12 @@
private static final String TAG = "ScrimController";
private static final boolean DEBUG = false;
+ public static final long ANIMATION_DURATION = 220;
+
private static final float SCRIM_BEHIND_ALPHA = 0.62f;
private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.55f;
private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
- private static final long ANIMATION_DURATION = 220;
private static final int TAG_KEY_ANIM = R.id.scrim;
private static final long PULSE_IN_ANIMATION_DURATION = 1000;
@@ -131,6 +132,7 @@
mDozing = dozing;
if (!mDozing) {
cancelPulsing();
+ mAnimateChange = true;
}
scheduleUpdate();
}
@@ -163,7 +165,7 @@
if (mAnimateKeyguardFadingOut) {
setScrimInFrontColor(0f);
setScrimBehindColor(0f);
- }else if (!mKeyguardShowing && !mBouncerShowing) {
+ } else if (!mKeyguardShowing && !mBouncerShowing) {
updateScrimNormal();
setScrimInFrontColor(0);
} else {
@@ -217,8 +219,8 @@
mScrimInFront.setClickable(false);
} else {
- // Eat touch events.
- mScrimInFront.setClickable(true);
+ // Eat touch events (unless dozing).
+ mScrimInFront.setClickable(!mDozing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
index 562f550..3f5cf3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SecureCameraLaunchManager.java
@@ -85,12 +85,12 @@
private KeyguardBottomAreaView mKeyguardBottomArea;
private CameraManager mCameraManager;
- private CameraAvailabilityListener mCameraAvailabilityListener;
+ private CameraAvailabilityCallback mCameraAvailabilityCallback;
private Map<String, Boolean> mCameraAvailabilityMap;
private boolean mWaitingToLaunchSecureCamera;
private Runnable mLaunchCameraRunnable;
- private class CameraAvailabilityListener extends CameraManager.AvailabilityListener {
+ private class CameraAvailabilityCallback extends CameraManager.AvailabilityCallback {
@Override
public void onCameraUnavailable(String cameraId) {
if (DEBUG) Log.d(TAG, "onCameraUnavailble(" + cameraId + ")");
@@ -123,10 +123,10 @@
mKeyguardBottomArea = keyguardBottomArea;
mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
- mCameraAvailabilityListener = new CameraAvailabilityListener();
+ mCameraAvailabilityCallback = new CameraAvailabilityCallback();
// An onCameraAvailable() or onCameraUnavailable() callback will be received for each camera
- // when the availability listener is registered, thus initializing the map.
+ // when the availability callback is registered, thus initializing the map.
//
// Keeping track of the state of all cameras using the onCameraAvailable() and
// onCameraUnavailable() callbacks can get messy when dealing with hot-pluggable cameras.
@@ -150,14 +150,14 @@
* Initializes the SecureCameraManager and starts listening for camera availability.
*/
public void create() {
- mCameraManager.addAvailabilityListener(mCameraAvailabilityListener, mHandler);
+ mCameraManager.registerAvailabilityCallback(mCameraAvailabilityCallback, mHandler);
}
/**
* Stops listening for camera availability and cleans up the SecureCameraManager.
*/
public void destroy() {
- mCameraManager.removeAvailabilityListener(mCameraAvailabilityListener);
+ mCameraManager.unregisterAvailabilityCallback(mCameraAvailabilityCallback);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index eeb97e3..15a7229 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -497,20 +497,19 @@
} else if (v == mAlarmStatus && mNextAlarm != null) {
PendingIntent showIntent = mNextAlarm.getShowIntent();
if (showIntent != null && showIntent.isActivity()) {
- mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */,
- false /* afterKeyguardGone */);
+ mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
}
}
}
private void startSettingsActivity() {
mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
- true /* dismissShade */, false /* afterKeyguardGone */);
+ true /* dismissShade */);
}
private void startBatteryActivity() {
mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY),
- true /* dismissShade */, false /* afterKeyguardGone */);
+ true /* dismissShade */);
}
public void setQSPanel(QSPanel qsp) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1811d8d..a5217ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -128,6 +128,10 @@
&& mService.getBarState() == StatusBarState.KEYGUARD
&& !mService.isBouncerShowing()) {
intercept = mDragDownHelper.onInterceptTouchEvent(ev);
+ // wake up on a touch down event, if dozing
+ if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mService.wakeUpIfDozing(ev.getEventTime());
+ }
}
if (!intercept) {
super.onInterceptTouchEvent(ev);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 70eaa5c..6f021ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -81,7 +81,7 @@
if (mCameraId != null) {
ensureHandler();
- mCameraManager.addAvailabilityListener(mAvailabilityListener, mHandler);
+ mCameraManager.registerAvailabilityCallback(mAvailabilityCallback, mHandler);
}
}
@@ -339,8 +339,8 @@
}
};
- private final CameraManager.AvailabilityListener mAvailabilityListener =
- new CameraManager.AvailabilityListener() {
+ private final CameraManager.AvailabilityCallback mAvailabilityCallback =
+ new CameraManager.AvailabilityCallback() {
@Override
public void onCameraAvailable(String cameraId) {
if (DEBUG) Log.d(TAG, "onCameraAvailable(" + cameraId + ")");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index b2009c3..7f155a1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -28,6 +28,7 @@
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.systemui.ExpandHelper;
@@ -111,6 +112,7 @@
mContentHolder.setVisibility(View.VISIBLE);
mContentHolder.setAlpha(mMaxAlpha);
mContentHolder.addView(mHeadsUp.row);
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
mSwipeHelper.snapChild(mContentHolder, 1f);
mStartTouchTime = System.currentTimeMillis() + mTouchSensitivityDelay;
@@ -126,6 +128,14 @@
return true;
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (changedView.getVisibility() == VISIBLE) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ }
+ }
+
public boolean isShowing(String key) {
return mHeadsUp != null && mHeadsUp.key.equals(key);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index d9a3e14..16c0e66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -18,10 +18,12 @@
import android.animation.Animator;
import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
+import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -57,6 +59,7 @@
private boolean mSupportsLongpress = true;
private Animator mAnimateToQuiescent = new ObjectAnimator();
private Drawable mBackground;
+ private AudioManager mAudioManager;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -99,6 +102,7 @@
setClickable(true);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
@Override
@@ -251,6 +255,10 @@
return true;
}
+ public void playSoundEffect(int soundConstant) {
+ mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());
+ };
+
public void sendEvent(int action, int flags) {
sendEvent(action, flags, SystemClock.uptimeMillis());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index b64dcbe..2ed9366 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -30,7 +30,8 @@
void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
boolean activityIn, boolean activityOut,
- String dataTypeContentDescriptionId, String description, boolean noSim);
+ String dataTypeContentDescriptionId, String description, boolean noSim,
+ boolean isDataTypeIconWide);
void onAirplaneModeChanged(boolean enabled);
void onMobileDataEnabled(boolean enabled);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4a6f1a8..5088089 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -63,9 +63,6 @@
static final boolean DEBUG = false;
static final boolean CHATTY = false; // additional diagnostics, but not logspew
- private static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
- private static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
-
// telephony
boolean mHspaDataDistinguishable;
final TelephonyManager mPhone;
@@ -165,7 +162,8 @@
public interface SignalCluster {
void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming);
+ String contentDescription, String typeContentDescription, boolean roaming,
+ boolean isTypeIconWide);
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
@@ -358,6 +356,16 @@
mMobileDataController.setMobileDataEnabled(enabled);
}
+ private boolean isTypeIconWide(int iconId) {
+ return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId
+ || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId;
+ }
+
+ private boolean isQsTypeIconWide(int iconId) {
+ return TelephonyIcons.QS_ICON_LTE == iconId || TelephonyIcons.QS_ICON_1X == iconId
+ || TelephonyIcons.QS_ICON_3G == iconId || TelephonyIcons.QS_ICON_4G == iconId;
+ }
+
public void refreshSignalCluster(SignalCluster cluster) {
if (mDemoMode) return;
cluster.setWifiIndicators(
@@ -374,7 +382,8 @@
mDataTypeIconId,
mContentDescriptionWimax,
mContentDescriptionDataType,
- mDataTypeIconId == ROAMING_ICON);
+ mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ false /* isTypeIconWide */ );
} else {
// normal mobile data
cluster.setMobileDataIndicators(
@@ -383,7 +392,8 @@
mDataTypeIconId,
mContentDescriptionPhoneSignal,
mContentDescriptionDataType,
- mDataTypeIconId == ROAMING_ICON);
+ mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ isTypeIconWide(mDataTypeIconId));
}
cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
}
@@ -409,18 +419,20 @@
if (isEmergencyOnly()) {
cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, null, mNoSim);
+ mContentDescriptionDataType, null, mNoSim, isQsTypeIconWide(mQSDataTypeIconId));
} else {
if (mIsWimaxEnabled && mWimaxConnected) {
// Wimax is special
cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim);
+ mContentDescriptionDataType, mNetworkName, mNoSim,
+ isQsTypeIconWide(mQSDataTypeIconId));
} else {
// Normal mobile data
cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
- mContentDescriptionDataType, mNetworkName, mNoSim);
+ mContentDescriptionDataType, mNetworkName, mNoSim,
+ isQsTypeIconWide(mQSDataTypeIconId));
}
}
cb.onAirplaneModeChanged(mAirplaneMode);
@@ -754,7 +766,7 @@
R.string.accessibility_data_connection_4g);
} else {
mDataIconList = TelephonyIcons.DATA_LTE[mInetCondition];
- mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_lte;
+ mDataTypeIconId = TelephonyIcons.ICON_LTE;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[mInetCondition];
mContentDescriptionDataType = mContext.getString(
R.string.accessibility_data_connection_lte);
@@ -780,11 +792,11 @@
if (isCdma()) {
if (isCdmaEri()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
} else if (mPhone.isNetworkRoaming()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
}
@@ -928,8 +940,8 @@
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean wasConnected = mWifiConnected;
mWifiConnected = networkInfo != null && networkInfo.isConnected();
- // If we just connected, grab the inintial signal strength and ssid
- if (mWifiConnected && !wasConnected) {
+ // If Connected grab the signal strength and ssid
+ if (mWifiConnected) {
// try getting it out of the intent first
WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (info == null) {
@@ -1164,7 +1176,7 @@
// look again; your radios are now airplanes
mContentDescriptionPhoneSignal = mContext.getString(
R.string.accessibility_airplane_mode);
- mAirplaneIconId = FLIGHT_MODE_ICON;
+ mAirplaneIconId = TelephonyIcons.FLIGHT_MODE_ICON;
mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
mQSPhoneSignalIconId = 0;
@@ -1198,11 +1210,11 @@
mQSDataTypeIconId = 0;
if (isCdma()) {
if (isCdmaEri()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
} else if (mPhone.isNetworkRoaming()) {
- mDataTypeIconId = ROAMING_ICON;
+ mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
}
}
@@ -1509,7 +1521,7 @@
if (airplane != null) {
boolean show = airplane.equals("show");
for (SignalCluster cluster : mSignalClusters) {
- cluster.setIsAirplaneMode(show, FLIGHT_MODE_ICON);
+ cluster.setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON);
}
}
String fully = args.getString("fully");
@@ -1540,23 +1552,23 @@
String datatype = args.getString("datatype");
if (datatype != null) {
mDemoDataTypeIconId =
- datatype.equals("1x") ? R.drawable.stat_sys_data_fully_connected_1x :
- datatype.equals("3g") ? R.drawable.stat_sys_data_fully_connected_3g :
- datatype.equals("4g") ? R.drawable.stat_sys_data_fully_connected_4g :
+ datatype.equals("1x") ? TelephonyIcons.ICON_1X :
+ datatype.equals("3g") ? TelephonyIcons.ICON_3G :
+ datatype.equals("4g") ? TelephonyIcons.ICON_4G :
datatype.equals("e") ? R.drawable.stat_sys_data_fully_connected_e :
datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g :
datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h :
- datatype.equals("lte") ? R.drawable.stat_sys_data_fully_connected_lte :
- datatype.equals("roam") ? ROAMING_ICON :
+ datatype.equals("lte") ? TelephonyIcons.ICON_LTE :
+ datatype.equals("roam") ? TelephonyIcons.ROAMING_ICON :
0;
mDemoQSDataTypeIconId =
- datatype.equals("1x") ? R.drawable.ic_qs_signal_1x :
- datatype.equals("3g") ? R.drawable.ic_qs_signal_3g :
- datatype.equals("4g") ? R.drawable.ic_qs_signal_4g :
+ datatype.equals("1x") ? TelephonyIcons.QS_ICON_1X :
+ datatype.equals("3g") ? TelephonyIcons.QS_ICON_3G :
+ datatype.equals("4g") ? TelephonyIcons.QS_ICON_4G :
datatype.equals("e") ? R.drawable.ic_qs_signal_e :
datatype.equals("g") ? R.drawable.ic_qs_signal_g :
datatype.equals("h") ? R.drawable.ic_qs_signal_h :
- datatype.equals("lte") ? R.drawable.ic_qs_signal_lte :
+ datatype.equals("lte") ? TelephonyIcons.QS_ICON_LTE :
datatype.equals("roam") ? R.drawable.ic_qs_signal_r :
0;
}
@@ -1575,7 +1587,8 @@
mDemoDataTypeIconId,
"Demo",
"Demo",
- mDemoDataTypeIconId == ROAMING_ICON);
+ mDemoDataTypeIconId == TelephonyIcons.ROAMING_ICON,
+ isTypeIconWide(mDemoDataTypeIconId));
}
refreshViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index cdbe494..030cd6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -20,14 +20,12 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardActivityLauncher;
import com.android.systemui.statusbar.phone.KeyguardPreviewContainer;
import java.util.List;
@@ -107,20 +105,21 @@
return info;
}
- public boolean wouldLaunchResolverActivity(Intent intent) {
- PackageManager packageManager = mContext.getPackageManager();
+ public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
+ int currentUserId) {
+ PackageManager packageManager = ctx.getPackageManager();
final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
- intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
+ intent, PackageManager.MATCH_DEFAULT_ONLY, currentUserId);
if (appList.size() == 0) {
return false;
}
ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
- PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA,
- mLockPatternUtils.getCurrentUser());
+ PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, currentUserId);
return wouldLaunchResolverActivity(resolved, appList);
}
- private boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
+ private static boolean wouldLaunchResolverActivity(
+ ResolveInfo resolved, List<ResolveInfo> appList) {
// If the list contains the above resolved activity, then it can't be
// ResolverActivity itself.
for (int i = 0; i < appList.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index a15ddaf..2fbb812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -139,14 +139,14 @@
}
@Override
- public void addCallback(SecurityControllerCallback callback) {
+ public void removeCallback(SecurityControllerCallback callback) {
if (callback == null) return;
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
mCallbacks.remove(callback);
}
@Override
- public void removeCallback(SecurityControllerCallback callback) {
+ public void addCallback(SecurityControllerCallback callback) {
if (callback == null || mCallbacks.contains(callback)) return;
if (DEBUG) Log.d(TAG, "addCallback " + callback);
mCallbacks.add(callback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 84c53ce..1f2b918 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -188,5 +188,16 @@
R.drawable.ic_qs_signal_lte
};
+ static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
+ static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
+ static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+ static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
+ static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
+ static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
+
+ static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte;
+ static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
+ static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
+ static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e4b1945..d02826f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -73,6 +73,7 @@
private ArrayList<UserRecord> mUsers = new ArrayList<>();
private Dialog mExitGuestDialog;
+ private Dialog mAddUserDialog;
private int mLastNonGuestUser = UserHandle.USER_OWNER;
private boolean mSimpleUserSwitcher;
private boolean mAddUsersWhenLocked;
@@ -228,8 +229,8 @@
// No guest user. Create one.
id = mUserManager.createGuest(mContext, mContext.getString(R.string.guest_nickname)).id;
} else if (record.isAddUser) {
- id = mUserManager.createUser(
- mContext.getString(R.string.user_new_user_name), 0 /* flags */).id;
+ showAddUserDialog();
+ return;
} else {
id = record.info.id;
}
@@ -260,6 +261,14 @@
mExitGuestDialog.show();
}
+ private void showAddUserDialog() {
+ if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
+ mAddUserDialog.cancel();
+ }
+ mAddUserDialog = new AddUserDialog(mContext);
+ mAddUserDialog.show();
+ }
+
private void exitGuest(int id) {
int newId = UserHandle.USER_OWNER;
if (mLastNonGuestUser != UserHandle.USER_OWNER) {
@@ -334,6 +343,14 @@
}
}
+ public String getCurrentUserName(Context context) {
+ if (mUsers.isEmpty()) return null;
+ UserRecord item = mUsers.get(0);
+ if (item == null || item.info == null) return null;
+ if (item.isGuest) return context.getString(R.string.guest_nickname);
+ return item.info.name;
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -526,4 +543,30 @@
}
}
}
+
+ private final class AddUserDialog extends SystemUIDialog implements
+ DialogInterface.OnClickListener {
+
+ public AddUserDialog(Context context) {
+ super(context);
+ setTitle(R.string.user_add_user_title);
+ setMessage(context.getString(R.string.user_add_user_message_short));
+ setButton(DialogInterface.BUTTON_NEGATIVE,
+ context.getString(android.R.string.cancel), this);
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(android.R.string.ok), this);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == BUTTON_NEGATIVE) {
+ cancel();
+ } else {
+ dismiss();
+ int id = mUserManager.createUser(
+ mContext.getString(R.string.user_new_user_name), 0 /* flags */).id;
+ switchToUserId(id);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index ddb5cb8..8e677f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -32,7 +32,6 @@
private float mOverScrollTopAmount;
private float mOverScrollBottomAmount;
private int mSpeedBumpIndex = -1;
- private float mScrimAmount;
private boolean mDark;
private boolean mHideSensitive;
@@ -105,14 +104,6 @@
}
}
- public void setScrimAmount(float scrimAmount) {
- mScrimAmount = scrimAmount;
- }
-
- public float getScrimAmount() {
- return mScrimAmount;
- }
-
public float getOverScrollAmount(boolean top) {
return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index fed579c..67ba8d20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -40,6 +40,7 @@
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.SpeedBumpView;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.policy.ScrollAdapter;
import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
@@ -645,7 +646,7 @@
@Override
public boolean isAntiFalsingNeeded() {
- return mPhoneStatusBar.isFalsingThresholdNeeded();
+ return mPhoneStatusBar.getBarState() == StatusBarState.KEYGUARD;
}
private void setSwipingInProgress(boolean isSwiped) {
@@ -1546,7 +1547,7 @@
mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
- updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
+ updateAnimationState(child);
}
public void setAnimationsEnabled(boolean animationsEnabled) {
@@ -1563,6 +1564,11 @@
}
}
+ private void updateAnimationState(View child) {
+ updateAnimationState(mAnimationsEnabled && mIsExpanded, child);
+ }
+
+
private void updateAnimationState(boolean running, View child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -1960,6 +1966,7 @@
mRequestViewResizeAnimationOnLayout = true;
}
mStackScrollAlgorithm.onReset(view);
+ updateAnimationState(view);
}
private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
@@ -2094,13 +2101,6 @@
return true;
}
- public void setScrimAlpha(float progress) {
- if (progress != mAmbientState.getScrimAmount()) {
- mAmbientState.setScrimAmount(progress);
- requestChildrenUpdate();
- }
- }
-
/**
* See {@link AmbientState#setDark}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index fe855d9..e4a1c27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -40,8 +40,6 @@
private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
private static final int MAX_ITEMS_IN_TOP_STACK = 3;
- /** When a child is activated, the other cards' alpha fade to this value. */
- private static final float ACTIVATED_INVERSE_ALPHA = 0.9f;
public static final float DIMMED_SCALE = 0.95f;
private int mPaddingBetweenElements;
@@ -172,7 +170,6 @@
handleDraggedViews(ambientState, resultState, algorithmState);
updateDimmedActivatedHideSensitive(ambientState, resultState, algorithmState);
updateClipping(resultState, algorithmState);
- updateScrimAmount(resultState, algorithmState, ambientState.getScrimAmount());
updateSpeedBumpState(resultState, algorithmState, ambientState.getSpeedBumpIndex());
}
@@ -189,16 +186,6 @@
}
}
- private void updateScrimAmount(StackScrollState resultState,
- StackScrollAlgorithmState algorithmState, float scrimAmount) {
- int childCount = algorithmState.visibleChildren.size();
- for (int i = 0; i < childCount; i++) {
- View child = algorithmState.visibleChildren.get(i);
- StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
- childViewState.scrimAmount = scrimAmount;
- }
- }
-
private void updateClipping(StackScrollState resultState,
StackScrollAlgorithmState algorithmState) {
float previousNotificationEnd = 0;
@@ -281,12 +268,8 @@
childViewState.scale = !mScaleDimmed || !dimmed || isActivatedChild
? 1.0f
: DIMMED_SCALE;
- if (dimmed && activatedChild != null) {
- if (!isActivatedChild) {
- childViewState.alpha *= ACTIVATED_INVERSE_ALPHA;
- } else {
- childViewState.zTranslation += 2.0f * mZDistanceBetweenElements;
- }
+ if (dimmed && isActivatedChild) {
+ childViewState.zTranslation += 2.0f * mZDistanceBetweenElements;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index f7a2824..0967ecd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -165,9 +165,6 @@
// apply speed bump state
child.setBelowSpeedBump(state.belowSpeedBump);
- // apply scrimming
- child.setScrimAmount(state.scrimAmount);
-
// apply clipping
float oldClipTopAmount = child.getClipTopAmount();
if (oldClipTopAmount != state.clipTopAmount) {
@@ -252,12 +249,6 @@
boolean belowSpeedBump;
/**
- * A value between 0 and 1 indicating how much the view should be scrimmed.
- * 1 means that the notifications will be darkened as much as possible.
- */
- float scrimAmount;
-
- /**
* The amount which the view should be clipped from the top. This is calculated to
* perceive consistent shadows.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 58d5813..ece82a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -251,9 +251,6 @@
child.setHideSensitive(viewState.hideSensitive, mAnimationFilter.animateHideSensitive &&
!wasAdded && !noAnimation, delay, duration);
- // apply scrimming
- child.setScrimAmount(viewState.scrimAmount);
-
if (wasAdded) {
child.performAddAnimation(delay, mCurrentLength);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 5da8681..6949ffb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -56,6 +56,7 @@
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import android.widget.SeekBar;
@@ -1055,11 +1056,11 @@
if (sc != null) {
if (streamType == STREAM_REMOTE_MUSIC && controller != sc.controller) {
if (sc.controller != null) {
- sc.controller.removeCallback(mMediaControllerCb);
+ sc.controller.unregisterCallback(mMediaControllerCb);
}
sc.controller = controller;
if (controller != null) {
- sc.controller.addCallback(mMediaControllerCb);
+ sc.controller.registerCallback(mMediaControllerCb);
}
}
if (sc.seekbarView.getMax() != max) {
@@ -1078,6 +1079,7 @@
if (mCallback != null) {
mCallback.onVisible(true);
}
+ announceDialogShown();
}
// Do a little vibrate if applicable (only when going into vibrate mode)
@@ -1094,6 +1096,10 @@
}
}
+ private void announceDialogShown() {
+ mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ }
+
private boolean isShowing() {
return mDialog.isShowing();
}
@@ -1175,7 +1181,7 @@
StreamControl sc = mStreamControls.get(STREAM_REMOTE_MUSIC);
if (sc != null) {
if (sc.controller != null) {
- sc.controller.removeCallback(mMediaControllerCb);
+ sc.controller.unregisterCallback(mMediaControllerCb);
sc.controller = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index acb4827..0586a83 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -140,8 +140,7 @@
@Override
public void run() {
getComponent(PhoneStatusBar.class).startActivityDismissingKeyguard(
- ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */,
- false /* afterKeyguardGone */);
+ ZenModePanel.ZEN_SETTINGS, true /* onlyProvisioned */, true /* dismissShade */);
mPanel.postDismiss(mDismissDelay);
}
};
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 41695c1..7b41391 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -413,7 +413,7 @@
@Override
public void onPress() {
Intent intent = new Intent(Settings.ACTION_SETTINGS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(intent);
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 81a838a..cce30c7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2755,12 +2755,14 @@
SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
mStatusBarColor, mLastTopInset, Gravity.TOP,
STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground);
+ com.android.internal.R.id.statusBarBackground,
+ (getAttributes().flags & FLAG_FULLSCREEN) != 0);
mNavigationColorView = updateColorViewInt(mNavigationColorView,
SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
mNavigationBarColor, mLastBottomInset, Gravity.BOTTOM,
NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground);
+ com.android.internal.R.id.navigationBarBackground,
+ false /* hiddenByWindowFlag */);
}
if (insets != null) {
insets = insets.consumeStableInsets();
@@ -2769,8 +2771,10 @@
}
private View updateColorViewInt(View view, int systemUiHideFlag, int translucentFlag,
- int color, int height, int verticalGravity, String transitionName, int id) {
+ int color, int height, int verticalGravity, String transitionName, int id,
+ boolean hiddenByWindowFlag) {
boolean show = height > 0 && (mLastSystemUiVisibility & systemUiHideFlag) == 0
+ && !hiddenByWindowFlag
&& (getAttributes().flags & translucentFlag) == 0
&& (color & Color.BLACK) != 0
&& (getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -2890,7 +2894,6 @@
invalidate();
int opacity = PixelFormat.OPAQUE;
-
// Note: if there is no background, we will assume opaque. The
// common case seems to be that an application sets there to be
// no background so it can draw everything itself. For that,
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e382a9f..16bb00b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -66,6 +66,7 @@
import android.os.UEventObserver;
import android.os.UserHandle;
import android.os.Vibrator;
+import android.provider.MediaStore;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.service.dreams.DreamService;
@@ -127,6 +128,9 @@
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
/**
* WindowManagerPolicy implementation for the Android phone UI. This
@@ -315,6 +319,7 @@
boolean mLanguageSwitchKeyPressed;
int mLidState = LID_ABSENT;
+ int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
boolean mHaveBuiltInKeyboard;
boolean mSystemReady;
@@ -1525,6 +1530,10 @@
mLidState = mWindowManagerFuncs.getLidState();
}
+ private void readCameraLensCoverState() {
+ mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState();
+ }
+
private boolean isHidden(int accessibilityMode) {
switch (accessibilityMode) {
case 1:
@@ -2400,7 +2409,7 @@
if (down) {
mPendingMetaAction = true;
} else if (mPendingMetaAction) {
- launchAssistAction();
+ launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD);
}
return -1;
}
@@ -2620,10 +2629,17 @@
}
private void launchAssistAction() {
+ launchAssistAction(null);
+ }
+
+ private void launchAssistAction(String hint) {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent != null) {
+ if (hint != null) {
+ intent.putExtra(hint, true);
+ }
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -3517,13 +3533,16 @@
pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop
+ mOverscanScreenHeight;
} else if (attrs.type == TYPE_WALLPAPER) {
- // The wallpaper also has Real Ultimate Power.
- pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft;
- pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop;
- pf.right = df.right = of.right = cf.right
- = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
- pf.bottom = df.bottom = of.bottom = cf.bottom
- = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
+ // The wallpaper also has Real Ultimate Power, but we want to tell
+ // it about the overscan area.
+ pf.left = df.left = mOverscanScreenLeft;
+ pf.top = df.top = mOverscanScreenTop;
+ pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth;
+ pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight;
+ of.left = cf.left = mUnrestrictedScreenLeft;
+ of.top = cf.top = mUnrestrictedScreenTop;
+ of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
+ of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
} else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0
&& attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
@@ -3637,9 +3656,12 @@
// TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it.
if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) {
- df.left = df.top = of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
- df.right = df.bottom = of.right = of.bottom = cf.right = cf.bottom
- = vf.right = vf.bottom = 10000;
+ df.left = df.top = -10000;
+ df.right = df.bottom = 10000;
+ if (attrs.type != TYPE_WALLPAPER) {
+ of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000;
+ of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
+ }
}
if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle()
@@ -4055,6 +4077,27 @@
}
}
+ @Override
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+ int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED;
+ if (mCameraLensCoverState == lensCoverState) {
+ return;
+ }
+ if (mCameraLensCoverState == CAMERA_LENS_COVERED &&
+ lensCoverState == CAMERA_LENS_UNCOVERED) {
+ Intent intent;
+ final boolean keyguardActive = mKeyguardDelegate == null ? false :
+ mKeyguardDelegate.isShowing();
+ if (keyguardActive) {
+ intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
+ } else {
+ intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
+ }
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ }
+ mCameraLensCoverState = lensCoverState;
+ }
+
void setHdmiPlugged(boolean plugged) {
if (mHdmiPlugged != plugged) {
mHdmiPlugged = plugged;
@@ -4204,9 +4247,16 @@
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
if (interactive || (isInjected && !isWakeKey)) {
- // When the screen is on or if the key is injected pass the key to the application.
+ // When the device is interactive or the key is injected pass the key to the
+ // application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
+ } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
+ // If we're currently dozing with the screen on and the keyguard showing, pass the key
+ // to the application but preserve its wake key status to make sure we still move
+ // from dozing to fully interactive if we would normally go from off to fully
+ // interactive.
+ result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
@@ -4511,14 +4561,22 @@
/** {@inheritDoc} */
@Override
- public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
- // We already know this is a wake motion so just wake up.
- // Note that we would observe policyFlags containing
- // FLAG_WAKE and FLAG_INTERACTIVE here.
- mPowerManager.wakeUp(whenNanos / 1000000);
+ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ if ((policyFlags & FLAG_WAKE) != 0) {
+ mPowerManager.wakeUp(whenNanos / 1000000);
+ return 0;
+ }
+ if (shouldDispatchInputWhenNonInteractive()) {
+ return ACTION_PASS_TO_USER;
+ }
return 0;
}
+ private boolean shouldDispatchInputWhenNonInteractive() {
+ return keyguardIsShowingTq() && mDisplay != null &&
+ mDisplay.getState() != Display.STATE_OFF;
+ }
+
void dispatchMediaKeyWithWakeLock(KeyEvent event) {
if (DEBUG_INPUT) {
Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
@@ -5132,6 +5190,7 @@
mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
mKeyguardDelegate.onSystemReady();
+ readCameraLensCoverState();
updateUiMode();
synchronized (mLock) {
updateOrientationListenerLp();
@@ -5783,6 +5842,7 @@
pw.print(" mSystemBooted="); pw.println(mSystemBooted);
pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
+ pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState);
pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
|| mForceClearedSystemUiFlags != 0) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 5d13fed..ebe21ff 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -746,14 +746,16 @@
}
/**
- * Gets the bounds of the accessibility focus in the active window.
+ * Gets a point within the accessibility focused node where we can send down
+ * and up events to perform a click.
*
- * @param outBounds The output to which to write the focus bounds.
- * @return Whether accessibility focus was found and the bounds are populated.
+ * @param outPoint The click point to populate.
+ * @return Whether accessibility a click point was found and set.
*/
// TODO: (multi-display) Make sure this works for multiple displays.
- boolean getAccessibilityFocusBounds(Rect outBounds) {
- return getInteractionBridgeLocked().getAccessibilityFocusBoundsNotLocked(outBounds);
+ boolean getAccessibilityFocusClickPointInScreen(Point outPoint) {
+ return getInteractionBridgeLocked()
+ .getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
}
/**
@@ -2196,8 +2198,8 @@
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName,
- partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
- interrogatingTid, spec);
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2248,8 +2250,8 @@
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
- partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid,
- interrogatingTid, spec);
+ partialInteractiveRegion, interactionId, callback, mFetchFlags,
+ interrogatingPid, interrogatingTid, spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2352,8 +2354,9 @@
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
- connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, interactionId,
- callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+ connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion,
+ interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+ spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2403,8 +2406,9 @@
final long identityToken = Binder.clearCallingIdentity();
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
try {
- connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, interactionId,
- callback, mFetchFlags, interrogatingPid, interrogatingTid, spec);
+ connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion,
+ interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
+ spec);
return true;
} catch (RemoteException re) {
if (DEBUG) {
@@ -2460,6 +2464,7 @@
return true;
}
+ @Override
public boolean performGlobalAction(int action) {
synchronized (mLock) {
// We treat calls from a profile as if made by its parent as profiles
@@ -2501,6 +2506,57 @@
}
@Override
+ public boolean computeClickPointInScreen(int accessibilityWindowId,
+ long accessibilityNodeId, int interactionId,
+ IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
+ throws RemoteException {
+ final int resolvedWindowId;
+ IAccessibilityInteractionConnection connection = null;
+ Region partialInteractiveRegion = mTempRegion;
+ synchronized (mLock) {
+ // We treat calls from a profile as if made by its parent as profiles
+ // share the accessibility state of the parent. The call below
+ // performs the current profile parent resolution.
+ final int resolvedUserId = mSecurityPolicy
+ .resolveCallingUserIdEnforcingPermissionsLocked(
+ UserHandle.getCallingUserId());
+ if (resolvedUserId != mCurrentUserId) {
+ return false;
+ }
+ resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
+ final boolean permissionGranted =
+ mSecurityPolicy.canRetrieveWindowContentLocked(this);
+ if (!permissionGranted) {
+ return false;
+ } else {
+ connection = getConnectionLocked(resolvedWindowId);
+ if (connection == null) {
+ return false;
+ }
+ }
+ if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
+ resolvedWindowId, partialInteractiveRegion)) {
+ partialInteractiveRegion = null;
+ }
+ }
+ final int interrogatingPid = Binder.getCallingPid();
+ final long identityToken = Binder.clearCallingIdentity();
+ MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
+ try {
+ connection.computeClickPointInScreen(accessibilityNodeId, partialInteractiveRegion,
+ interactionId, callback, interrogatingPid, interrogatingTid, spec);
+ return true;
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Error computeClickPointInScreen().");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ return false;
+ }
+
+ @Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
synchronized (mLock) {
@@ -3119,30 +3175,43 @@
}
}
- public boolean getAccessibilityFocusBoundsNotLocked(Rect outBounds) {
+ public boolean getAccessibilityFocusClickPointInScreenNotLocked(Point outPoint) {
AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
if (focus == null) {
return false;
}
synchronized (mLock) {
- focus.getBoundsInScreen(outBounds);
+ Point point = mClient.computeClickPointInScreen(mConnectionId,
+ focus.getWindowId(), focus.getSourceNodeId());
+
+ if (point == null) {
+ return false;
+ }
MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
if (spec != null && !spec.isNop()) {
- outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
- outBounds.scale(1 / spec.scale);
+ point.offset((int) -spec.offsetX, (int) -spec.offsetY);
+ point.x = (int) (point.x * (1 / spec.scale));
+ point.y = (int) (point.y * (1 / spec.scale));
}
- // Clip to the window rectangle.
+ // Make sure the point is within the window.
Rect windowBounds = mTempRect;
getActiveWindowBounds(windowBounds);
- outBounds.intersect(windowBounds);
+ if (!windowBounds.contains(point.x, point.y)) {
+ return false;
+ }
- // Clip to the screen rectangle.
- mDefaultDisplay.getRealSize(mTempPoint);
- outBounds.intersect(0, 0, mTempPoint.x, mTempPoint.y);
+ // Make sure the point is within the screen.
+ Point screenSize = mTempPoint;
+ mDefaultDisplay.getRealSize(screenSize);
+ if (point.x < 0 || point.x > screenSize.x
+ || point.y < 0 || point.y > screenSize.y) {
+ return false;
+ }
+ outPoint.set(point.x, point.y);
return true;
}
}
@@ -3484,11 +3553,16 @@
}
private void notifyWindowsChanged() {
- // Let the client know the windows changed.
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_WINDOWS_CHANGED);
- event.setEventTime(SystemClock.uptimeMillis());
- sendAccessibilityEvent(event, mCurrentUserId);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ // Let the client know the windows changed.
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_WINDOWS_CHANGED);
+ event.setEventTime(SystemClock.uptimeMillis());
+ sendAccessibilityEvent(event, mCurrentUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
public boolean canGetAccessibilityNodeInfoLocked(Service service, int windowId) {
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index af5c13d..9e63433 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -24,6 +24,7 @@
import android.gesture.GestureStore;
import android.gesture.GestureStroke;
import android.gesture.Prediction;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.SystemClock;
@@ -171,6 +172,9 @@
// Temporary rectangle to avoid instantiation.
private final Rect mTempRect = new Rect();
+ // Temporary point to avoid instantiation.
+ private final Point mTempPoint = new Point();
+
// Context in which this explorer operates.
private final Context mContext;
@@ -708,7 +712,6 @@
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
- mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
@@ -1158,18 +1161,18 @@
mInjectedPointerTracker.getLastInjectedHoverEventForClick();
if (lastExploreEvent == null) {
// No last touch explored event but there is accessibility focus in
- // the active window. We click in the middle of the focus bounds.
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
+ // the active window. We click in the focus bounds.
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
} else {
// Out of luck - do nothing.
return;
}
} else {
// If the click is within the active window but not within the
- // accessibility focus bounds we click in the focus center.
+ // accessibility focus bounds we click in the focus bounds.
final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1177,12 +1180,10 @@
if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
mAms.getActiveWindowBounds(activeWindowBounds);
if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- if (!focusBounds.contains(clickLocationX, clickLocationY)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
- }
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
}
}
}
@@ -1331,18 +1332,18 @@
mInjectedPointerTracker.getLastInjectedHoverEventForClick();
if (lastExploreEvent == null) {
// No last touch explored event but there is accessibility focus in
- // the active window. We click in the middle of the focus bounds.
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
+ // the active window. We click in the focus bounds.
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
} else {
// Out of luck - do nothing.
return;
}
} else {
// If the click is within the active window but not within the
- // accessibility focus bounds we click in the focus center.
+ // accessibility focus bounds we click in the focus bounds.
final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
clickLocationX = (int) lastExploreEvent.getX(lastExplorePointerIndex);
clickLocationY = (int) lastExploreEvent.getY(lastExplorePointerIndex);
@@ -1350,12 +1351,10 @@
if (mLastTouchedWindowId == mAms.getActiveWindowId()) {
mAms.getActiveWindowBounds(activeWindowBounds);
if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
- Rect focusBounds = mTempRect;
- if (mAms.getAccessibilityFocusBounds(focusBounds)) {
- if (!focusBounds.contains(clickLocationX, clickLocationY)) {
- clickLocationX = focusBounds.centerX();
- clickLocationY = focusBounds.centerY();
- }
+ Point point = mTempPoint;
+ if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
+ clickLocationX = point.x;
+ clickLocationY = point.y;
}
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7f7e5c3..d05de69 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -440,12 +440,10 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Permission Denial: can't dump from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+ "Permission Denial: can't dump from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
synchronized (mLock) {
int N = mProviders.size();
@@ -1863,7 +1861,7 @@
private void deleteProviderLocked(Provider provider) {
int N = provider.widgets.size();
- for (int i = 0; i < N; i++) {
+ for (int i = N - 1; i >= 0; i--) {
Widget widget = provider.widgets.remove(i);
// Call back with empty RemoteViews
updateAppWidgetInstanceLocked(widget, null, false);
@@ -4038,4 +4036,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3bab1bf..3062a92 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -425,8 +425,8 @@
TelephonyManager mTelephonyManager;
- // sequence number for Networks
- private final static int MIN_NET_ID = 10; // some reserved marks
+ // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp
+ private final static int MIN_NET_ID = 100; // some reserved marks
private final static int MAX_NET_ID = 65535;
private int mNextNetId = MIN_NET_ID;
@@ -793,14 +793,28 @@
}
/**
- * Check if UID should be blocked from using the network represented by the
- * given {@link NetworkStateTracker}.
+ * Check if UID should be blocked from using the network represented by the given networkType.
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
*/
private boolean isNetworkBlocked(int networkType, int uid) {
+ return isNetworkWithLinkPropertiesBlocked(getLinkPropertiesForType(networkType), uid);
+ }
+
+ /**
+ * Check if UID should be blocked from using the network represented by the given
+ * NetworkAgentInfo.
+ */
+ private boolean isNetworkBlocked(NetworkAgentInfo nai, int uid) {
+ return isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid);
+ }
+
+ /**
+ * Check if UID should be blocked from using the network with the given LinkProperties.
+ */
+ private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) {
final boolean networkCostly;
final int uidRules;
- LinkProperties lp = getLinkPropertiesForType(networkType);
final String iface = (lp == null ? "" : lp.getInterfaceName());
synchronized (mRulesLock) {
networkCostly = mMeteredIfaces.contains(iface);
@@ -819,17 +833,36 @@
* Return a filtered {@link NetworkInfo}, potentially marked
* {@link DetailedState#BLOCKED} based on
* {@link #isNetworkBlocked}.
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
*/
private NetworkInfo getFilteredNetworkInfo(int networkType, int uid) {
NetworkInfo info = getNetworkInfoForType(networkType);
return getFilteredNetworkInfo(info, networkType, uid);
}
+ /*
+ * @deprecated Uses mLegacyTypeTracker; cannot deal with multiple Networks of the same type.
+ */
private NetworkInfo getFilteredNetworkInfo(NetworkInfo info, int networkType, int uid) {
if (isNetworkBlocked(networkType, uid)) {
// network is blocked; clone and override state
info = new NetworkInfo(info);
info.setDetailedState(DetailedState.BLOCKED, null, null);
+ if (VDBG) log("returning Blocked NetworkInfo");
+ }
+ if (mLockdownTracker != null) {
+ info = mLockdownTracker.augmentNetworkInfo(info);
+ if (VDBG) log("returning Locked NetworkInfo");
+ }
+ return info;
+ }
+
+ private NetworkInfo getFilteredNetworkInfo(NetworkAgentInfo nai, int uid) {
+ NetworkInfo info = nai.networkInfo;
+ if (isNetworkBlocked(nai, uid)) {
+ // network is blocked; clone and override state
+ info = new NetworkInfo(info);
+ info.setDetailedState(DetailedState.BLOCKED, null, null);
if (DBG) log("returning Blocked NetworkInfo");
}
if (mLockdownTracker != null) {
@@ -946,7 +979,7 @@
synchronized (nai) {
if (nai.networkInfo == null) return null;
- return getFilteredNetworkInfo(nai.networkInfo, nai.networkInfo.getType(), uid);
+ return getFilteredNetworkInfo(nai, uid);
}
}
@@ -1315,6 +1348,12 @@
// }
}
+ private void enforceInternetPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERNET,
+ "ConnectivityService");
+ }
+
private void enforceAccessPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -2468,7 +2507,22 @@
}
public void reportBadNetwork(Network network) {
- //TODO
+ enforceAccessPermission();
+ enforceInternetPermission();
+
+ if (network == null) return;
+
+ final int uid = Binder.getCallingUid();
+ NetworkAgentInfo nai = null;
+ synchronized (mNetworkForNetId) {
+ nai = mNetworkForNetId.get(network.netId);
+ }
+ if (nai == null) return;
+ synchronized (nai) {
+ if (isNetworkBlocked(nai, uid)) return;
+
+ nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
+ }
}
public ProxyInfo getProxy() {
@@ -4436,10 +4490,14 @@
loge("Unknown NetworkAgentInfo in handleLingerComplete");
return;
}
- if (DBG) log("handleLingerComplete for " + oldNetwork.name());
if (DBG) {
- if (oldNetwork.networkRequests.size() != 0) {
- loge("Dead network still had " + oldNetwork.networkRequests.size() + " requests");
+ log("handleLingerComplete for " + oldNetwork.name());
+ for (int i = 0; i < oldNetwork.networkRequests.size(); i++) {
+ NetworkRequest nr = oldNetwork.networkRequests.valueAt(i);
+ // Ignore listening requests.
+ if (mNetworkRequests.get(nr).isRequest == false) continue;
+ loge("Dead network still had at least " + nr);
+ break;
}
}
oldNetwork.asyncChannel.disconnect();
@@ -4463,6 +4521,8 @@
loge("Unknown NetworkAgentInfo in handleConnectionValidated");
return;
}
+ if (newNetwork.validated) return;
+ newNetwork.validated = true;
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
if (DBG) log("handleConnectionValidated for "+newNetwork.name());
@@ -4706,6 +4766,8 @@
// code will fire.
for (int i = 0; i < nai.networkRequests.size(); i++) {
NetworkRequest nr = nai.networkRequests.valueAt(i);
+ // Don't send listening requests to factories. b/17393458
+ if (mNetworkRequests.get(nr).isRequest == false) continue;
sendUpdatedScoreToFactories(nr, score);
}
}
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 65ad1ce..b452a38 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -193,7 +193,7 @@
private final class BinderService extends IMms.Stub {
@Override
public void sendMessage(long subId, String callingPkg, Uri contentUri,
- String locationUrl, ContentValues configOverrides, PendingIntent sentIntent)
+ String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
throws RemoteException {
mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
@@ -206,7 +206,7 @@
@Override
public void downloadMessage(long subId, String callingPkg, String locationUrl,
- Uri contentUri, ContentValues configOverrides,
+ Uri contentUri, Bundle configOverrides,
PendingIntent downloadedIntent) throws RemoteException {
mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
"Download MMS message");
@@ -333,7 +333,7 @@
@Override
public void sendStoredMessage(long subId, String callingPkg, Uri messageUri,
- ContentValues configOverrides, PendingIntent sentIntent) throws RemoteException {
+ Bundle configOverrides, PendingIntent sentIntent) throws RemoteException {
mContext.enforceCallingPermission(Manifest.permission.SEND_SMS,
"Send stored MMS message");
if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java
index 2095152..59d50bd 100644
--- a/services/core/java/com/android/server/NativeDaemonEvent.java
+++ b/services/core/java/com/android/server/NativeDaemonEvent.java
@@ -201,20 +201,16 @@
}
while (current < length) {
// find the end of the word
- if (quoted) {
- wordEnd = current;
- while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) {
- if (rawEvent.charAt(wordEnd - 1) != '\\') {
- break;
- } else {
- wordEnd++; // skip this escaped quote and keep looking
- }
+ char terminator = quoted ? '\"' : ' ';
+ wordEnd = current;
+ while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
+ if (rawEvent.charAt(wordEnd) == '\\') {
+ // skip the escaped char
+ ++wordEnd;
}
- } else {
- wordEnd = rawEvent.indexOf(' ', current);
+ ++wordEnd;
}
- // if we didn't find the end-o-word token, take the rest of the string
- if (wordEnd == -1) wordEnd = length;
+ if (wordEnd > length) wordEnd = length;
String word = rawEvent.substring(current, wordEnd);
current += word.length();
if (!quoted) {
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index cf7e65c..cb1748d 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -397,8 +397,7 @@
break;
case NsdManager.NATIVE_DAEMON_EVENT:
NativeEvent event = (NativeEvent) msg.obj;
- if (!handleNativeEvent(event.code, event.raw,
- NativeDaemonEvent.unescapeArgs(event.raw))) {
+ if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
result = NOT_HANDLED;
}
break;
@@ -474,8 +473,14 @@
case NativeResponseCode.SERVICE_RESOLVED:
/* NNN resolveId fullName hostName port txtlen txtdata */
if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
- int index = cooked[2].indexOf(".");
- if (index == -1) {
+ int index = 0;
+ while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
+ if (cooked[2].charAt(index) == '\\') {
+ ++index;
+ }
+ ++index;
+ }
+ if (index >= cooked[2].length()) {
Slog.e(TAG, "Invalid service found " + raw);
break;
}
@@ -483,6 +488,8 @@
String rest = cooked[2].substring(index);
String type = rest.replace(".local.", "");
+ name = unescape(name);
+
clientInfo.mResolvedService.setServiceName(name);
clientInfo.mResolvedService.setServiceType(type);
clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
@@ -541,6 +548,30 @@
}
}
+ private String unescape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ if (++i >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = s.charAt(i);
+ if (c != '.' && c != '\\') {
+ if (i + 2 >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
+ i += 2;
+ }
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
private NativeDaemonConnector mNativeConnector;
private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
@@ -625,10 +656,12 @@
private class NativeEvent {
final int code;
final String raw;
+ final String[] cooked;
- NativeEvent(int code, String raw) {
+ NativeEvent(int code, String raw, String[] cooked) {
this.code = code;
this.raw = raw;
+ this.cooked = cooked;
}
}
@@ -644,7 +677,7 @@
public boolean onEvent(int code, String raw, String[] cooked) {
// TODO: NDC translates a message to a callback, we could enhance NDC to
// directly interact with a state machine through messages
- NativeEvent event = new NativeEvent(code, raw);
+ NativeEvent event = new NativeEvent(code, raw, cooked);
mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
return true;
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 7624314..37c23bb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -196,7 +196,7 @@
if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1);
int numPhones = TelephonyManager.getDefault().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
- TelephonyRegistry.this.notifyCellLocationUsingSubId(sub,
+ TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
mCellLocation[sub]);
}
break;
@@ -326,7 +326,7 @@
}
@Override
- public void listenUsingSubId(long subId, String pkgForDebug, IPhoneStateListener callback,
+ public void listenForSubscriber(long subId, String pkgForDebug, IPhoneStateListener callback,
int events, boolean notifyNow) {
listen(pkgForDebug, callback, events, notifyNow, subId, false);
}
@@ -542,12 +542,12 @@
broadcastCallStateChanged(state, incomingNumber, mDefaultSubId);
}
- public void notifyCallStateUsingSubId(long subId, int state, String incomingNumber) {
+ public void notifyCallStateForSubscriber(long subId, int state, String incomingNumber) {
if (!checkNotifyPermission("notifyCallState()")) {
return;
}
if (VDBG) {
- log("notifyCallStateUsingSubId: subId=" + subId
+ log("notifyCallStateForSubscriber: subId=" + subId
+ " state=" + state + " incomingNumber=" + incomingNumber);
}
synchronized (mRecords) {
@@ -573,38 +573,38 @@
}
public void notifyServiceState(ServiceState state) {
- notifyServiceStateUsingSubId(mDefaultSubId, state);
+ notifyServiceStateForSubscriber(mDefaultSubId, state);
}
- public void notifyServiceStateUsingSubId(long subId, ServiceState state) {
+ public void notifyServiceStateForSubscriber(long subId, ServiceState state) {
if (!checkNotifyPermission("notifyServiceState()")){
return;
}
if (subId == SubscriptionManager.DEFAULT_SUB_ID) {
subId = mDefaultSubId;
- if (VDBG) log("notifyServiceStateUsingSubId: using mDefaultSubId=" + mDefaultSubId);
+ if (VDBG) log("notifyServiceStateForSubscriber: using mDefaultSubId=" + mDefaultSubId);
}
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (VDBG) {
- log("notifyServiceStateUsingSubId: subId=" + subId + " phoneId=" + phoneId
+ log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
+ " state=" + state);
}
if (validatePhoneId(phoneId)) {
mServiceState[phoneId] = state;
- logServiceStateChanged("notifyServiceStateUsingSubId", subId, phoneId, state);
- if (VDBG) toStringLogSSC("notifyServiceStateUsingSubId");
+ logServiceStateChanged("notifyServiceStateForSubscriber", subId, phoneId, state);
+ if (VDBG) toStringLogSSC("notifyServiceStateForSubscriber");
for (Record r : mRecords) {
if (VDBG) {
- log("notifyServiceStateUsingSubId: r=" + r + " subId=" + subId
+ log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " state=" + state);
}
if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
(r.phoneId == phoneId)) {
try {
if (DBG) {
- log("notifyServiceStateUsingSubId: callback.onSSC r=" + r
+ log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " state=" + state);
}
@@ -615,7 +615,7 @@
}
}
} else {
- log("notifyServiceStateUsingSubId: INVALID phoneId=" + phoneId);
+ log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
}
handleRemoveListLocked();
}
@@ -623,33 +623,33 @@
}
public void notifySignalStrength(SignalStrength signalStrength) {
- notifySignalStrengthUsingSubId(mDefaultSubId, signalStrength);
+ notifySignalStrengthForSubscriber(mDefaultSubId, signalStrength);
}
- public void notifySignalStrengthUsingSubId(long subId, SignalStrength signalStrength) {
+ public void notifySignalStrengthForSubscriber(long subId, SignalStrength signalStrength) {
if (!checkNotifyPermission("notifySignalStrength()")) {
return;
}
if (VDBG) {
- log("notifySignalStrengthUsingSubId: subId=" + subId
+ log("notifySignalStrengthForSubscriber: subId=" + subId
+ " signalStrength=" + signalStrength);
- toStringLogSSC("notifySignalStrengthUsingSubId");
+ toStringLogSSC("notifySignalStrengthForSubscriber");
}
synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
- if (VDBG) log("notifySignalStrengthUsingSubId: valid phoneId=" + phoneId);
+ if (VDBG) log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId);
mSignalStrength[phoneId] = signalStrength;
for (Record r : mRecords) {
if (VDBG) {
- log("notifySignalStrengthUsingSubId: r=" + r + " subId=" + subId
+ log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId
+ " phoneId=" + phoneId + " ss=" + signalStrength);
}
if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
(r.phoneId == phoneId)) {
try {
if (DBG) {
- log("notifySignalStrengthUsingSubId: callback.onSsS r=" + r
+ log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " ss=" + signalStrength);
}
@@ -664,7 +664,7 @@
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
if (DBG) {
- log("notifySignalStrengthUsingSubId: callback.onSS r=" + r
+ log("notifySignalStrengthForSubscriber: callback.onSS r=" + r
+ " subId=" + subId + " phoneId=" + phoneId
+ " gsmSS=" + gsmSignalStrength + " ss=" + ss);
}
@@ -675,7 +675,7 @@
}
}
} else {
- log("notifySignalStrengthUsingSubId: invalid phoneId=" + phoneId);
+ log("notifySignalStrengthForSubscriber: invalid phoneId=" + phoneId);
}
handleRemoveListLocked();
}
@@ -683,15 +683,15 @@
}
public void notifyCellInfo(List<CellInfo> cellInfo) {
- notifyCellInfoUsingSubId(mDefaultSubId, cellInfo);
+ notifyCellInfoForSubscriber(mDefaultSubId, cellInfo);
}
- public void notifyCellInfoUsingSubId(long subId, List<CellInfo> cellInfo) {
+ public void notifyCellInfoForSubscriber(long subId, List<CellInfo> cellInfo) {
if (!checkNotifyPermission("notifyCellInfo()")) {
return;
}
if (VDBG) {
- log("notifyCellInfoUsingSubId: subId=" + subId
+ log("notifyCellInfoForSubscriber: subId=" + subId
+ " cellInfo=" + cellInfo);
}
@@ -743,15 +743,15 @@
}
public void notifyMessageWaitingChanged(boolean mwi) {
- notifyMessageWaitingChangedUsingSubId(mDefaultSubId, mwi);
+ notifyMessageWaitingChangedForSubscriber(mDefaultSubId, mwi);
}
- public void notifyMessageWaitingChangedUsingSubId(long subId, boolean mwi) {
+ public void notifyMessageWaitingChangedForSubscriber(long subId, boolean mwi) {
if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
return;
}
if (VDBG) {
- log("notifyMessageWaitingChangedUsingSubId: subId=" + subId
+ log("notifyMessageWaitingChangedForSubscriber: subId=" + subId
+ " mwi=" + mwi);
}
synchronized (mRecords) {
@@ -774,15 +774,15 @@
}
public void notifyCallForwardingChanged(boolean cfi) {
- notifyCallForwardingChangedUsingSubId(mDefaultSubId, cfi);
+ notifyCallForwardingChangedForSubscriber(mDefaultSubId, cfi);
}
- public void notifyCallForwardingChangedUsingSubId(long subId, boolean cfi) {
+ public void notifyCallForwardingChangedForSubscriber(long subId, boolean cfi) {
if (!checkNotifyPermission("notifyCallForwardingChanged()")) {
return;
}
if (VDBG) {
- log("notifyCallForwardingChangedUsingSubId: subId=" + subId
+ log("notifyCallForwardingChangedForSubscriber: subId=" + subId
+ " cfi=" + cfi);
}
synchronized (mRecords) {
@@ -805,10 +805,10 @@
}
public void notifyDataActivity(int state) {
- notifyDataActivityUsingSubId(mDefaultSubId, state);
+ notifyDataActivityForSubscriber(mDefaultSubId, state);
}
- public void notifyDataActivityUsingSubId(long subId, int state) {
+ public void notifyDataActivityForSubscriber(long subId, int state) {
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
@@ -831,12 +831,12 @@
public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
- notifyDataConnectionUsingSubId(mDefaultSubId, state, isDataConnectivityPossible,
+ notifyDataConnectionForSubscriber(mDefaultSubId, state, isDataConnectivityPossible,
reason, apn, apnType, linkProperties,
networkCapabilities, networkType, roaming);
}
- public void notifyDataConnectionUsingSubId(long subId, int state,
+ public void notifyDataConnectionForSubscriber(long subId, int state,
boolean isDataConnectivityPossible, String reason, String apn, String apnType,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int networkType, boolean roaming) {
@@ -844,7 +844,7 @@
return;
}
if (VDBG) {
- log("notifyDataConnectionUsingSubId: subId=" + subId
+ log("notifyDataConnectionForSubscriber: subId=" + subId
+ " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible
+ " reason='" + reason
+ "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
@@ -921,16 +921,16 @@
}
public void notifyDataConnectionFailed(String reason, String apnType) {
- notifyDataConnectionFailedUsingSubId(mDefaultSubId, reason, apnType);
+ notifyDataConnectionFailedForSubscriber(mDefaultSubId, reason, apnType);
}
- public void notifyDataConnectionFailedUsingSubId(long subId,
+ public void notifyDataConnectionFailedForSubscriber(long subId,
String reason, String apnType) {
if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
return;
}
if (VDBG) {
- log("notifyDataConnectionFailedUsingSubId: subId=" + subId
+ log("notifyDataConnectionFailedForSubscriber: subId=" + subId
+ " reason=" + reason + " apnType=" + apnType);
}
synchronized (mRecords) {
@@ -954,17 +954,17 @@
}
public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationUsingSubId(mDefaultSubId, cellLocation);
+ notifyCellLocationForSubscriber(mDefaultSubId, cellLocation);
}
- public void notifyCellLocationUsingSubId(long subId, Bundle cellLocation) {
- log("notifyCellLocationUsingSubId: subId=" + subId
+ public void notifyCellLocationForSubscriber(long subId, Bundle cellLocation) {
+ log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
return;
}
if (VDBG) {
- log("notifyCellLocationUsingSubId: subId=" + subId
+ log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
}
synchronized (mRecords) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 94d979e..888fa1a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -265,7 +265,11 @@
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context1, Intent intent) {
- purgeOldGrantsAll();
+ // Don't delete accounts when updating a authenticator's
+ // package.
+ if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ purgeOldGrantsAll();
+ }
}
}, intentFilter);
@@ -1700,9 +1704,10 @@
subtitle = titleAndSubtitle.substring(index + 1);
}
UserHandle user = new UserHandle(userId);
- n.color = mContext.getResources().getColor(
+ Context contextForUser = getContextForUser(user);
+ n.color = contextForUser.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color);
- n.setLatestEventInfo(mContext, title, subtitle,
+ n.setLatestEventInfo(contextForUser, title, subtitle,
PendingIntent.getActivityAsUser(mContext, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT, null, user));
installNotification(getCredentialPermissionNotificationId(
@@ -2968,11 +2973,12 @@
Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
0 /* when */);
UserHandle user = new UserHandle(userId);
+ Context contextForUser = getContextForUser(user);
final String notificationTitleFormat =
- mContext.getText(R.string.notification_title).toString();
- n.color = mContext.getResources().getColor(
+ contextForUser.getText(R.string.notification_title).toString();
+ n.color = contextForUser.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color);
- n.setLatestEventInfo(mContext,
+ n.setLatestEventInfo(contextForUser,
String.format(notificationTitleFormat, account.name),
message, PendingIntent.getActivityAsUser(
mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
@@ -3478,4 +3484,13 @@
}
return authTokensForAccount;
}
+
+ private Context getContextForUser(UserHandle user) {
+ try {
+ return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
+ } catch (NameNotFoundException e) {
+ // Default to mContext, not finding the package system is running as is unlikely.
+ return mContext;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0bdb964..599c3b9 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -308,7 +308,14 @@
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
+
ServiceRecord r = res.record;
+
+ if (!mAm.getUserManagerLocked().exists(r.userId)) {
+ Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId);
+ return null;
+ }
+
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2e9df8a..a9a4732 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -196,6 +196,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
+import dalvik.system.VMRuntime;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -3124,6 +3125,11 @@
requiredAbi = Build.SUPPORTED_ABIS[0];
}
+ String instructionSet = null;
+ if (app.info.primaryCpuAbi != null) {
+ instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
+ }
+
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
@@ -3131,7 +3137,8 @@
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
- app.info.targetSdkVersion, app.info.seinfo, requiredAbi, entryPointArgs);
+ app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
+ entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
if (app.isolated) {
@@ -3215,7 +3222,6 @@
if (resumed) {
if (mUsageStatsService != null) {
mUsageStatsService.reportEvent(component.realActivity, component.userId,
- System.currentTimeMillis(),
UsageEvents.Event.MOVE_TO_FOREGROUND);
}
synchronized (stats) {
@@ -3224,7 +3230,6 @@
} else {
if (mUsageStatsService != null) {
mUsageStatsService.reportEvent(component.realActivity, component.userId,
- System.currentTimeMillis(),
UsageEvents.Event.MOVE_TO_BACKGROUND);
}
synchronized (stats) {
@@ -6280,12 +6285,12 @@
}
@Override
- public final void activityPaused(IBinder token, PersistableBundle persistentState) {
+ public final void activityPaused(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
- stack.activityPausedLocked(token, false, persistentState);
+ stack.activityPausedLocked(token, false);
}
}
Binder.restoreCallingIdentity(origId);
@@ -9947,7 +9952,7 @@
}
private void updateEventDispatchingLocked() {
- mWindowManager.setEventDispatching(mBooted && !mWentToSleep && !mShuttingDown);
+ mWindowManager.setEventDispatching(mBooted && !mShuttingDown);
}
public void setLockScreenShown(boolean shown) {
@@ -10346,8 +10351,8 @@
final boolean translucentChanged = r.changeWindowTranslucency(false);
if (translucentChanged) {
r.task.stack.convertToTranslucent(r);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
}
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
mWindowManager.setAppFullscreen(token, false);
return translucentChanged;
}
@@ -15936,6 +15941,7 @@
newConfig.seq = mConfigurationSeq;
mConfiguration = newConfig;
Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + newConfig);
+ mUsageStatsService.reportConfigurationChange(newConfig, mCurrentUserId);
//mUsageStatsService.noteStartConfig(newConfig);
final Configuration configCopy = new Configuration(mConfiguration);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 77b4cc9..e043f03 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -698,12 +698,12 @@
case ActivityOptions.ANIM_SCALE_UP:
service.mWindowManager.overridePendingAppTransitionScaleUp(
pendingOptions.getStartX(), pendingOptions.getStartY(),
- pendingOptions.getStartWidth(), pendingOptions.getStartHeight());
+ pendingOptions.getWidth(), pendingOptions.getHeight());
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
- pendingOptions.getStartX()+pendingOptions.getStartWidth(),
- pendingOptions.getStartY()+pendingOptions.getStartHeight()));
+ pendingOptions.getStartX()+pendingOptions.getWidth(),
+ pendingOptions.getStartY()+pendingOptions.getHeight()));
}
break;
case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
@@ -728,15 +728,14 @@
service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
pendingOptions.getThumbnail(),
pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getWidth(), pendingOptions.getHeight(),
pendingOptions.getOnAnimationStartListener(),
(animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
if (intent.getSourceBounds() == null) {
intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
pendingOptions.getStartY(),
- pendingOptions.getStartX()
- + pendingOptions.getThumbnail().getWidth(),
- pendingOptions.getStartY()
- + pendingOptions.getThumbnail().getHeight()));
+ pendingOptions.getStartX() + pendingOptions.getWidth(),
+ pendingOptions.getStartY() + pendingOptions.getHeight()));
}
break;
default:
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3efd049..bcf3b17 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -241,6 +241,9 @@
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
+ /** Used to keep resumeTopActivityLocked() from being entered recursively */
+ private boolean inResumeTopActivity;
+
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -281,7 +284,7 @@
if (r.app != null) {
mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
}
- activityPausedLocked(r.appToken, true, r.persistentState);
+ activityPausedLocked(r.appToken, true);
}
} break;
case LAUNCH_TICK_MSG: {
@@ -422,13 +425,13 @@
}
final ActivityRecord topActivity() {
- // Iterate to find the first non-empty task stack. Note that this code can
- // be simplified once we stop storing tasks with empty mActivities lists.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
- final int topActivityNdx = activities.size() - 1;
- if (topActivityNdx >= 0) {
- return activities.get(topActivityNdx);
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (!r.finishing) {
+ return r;
+ }
}
}
return null;
@@ -456,7 +459,7 @@
final ActivityRecord r = ActivityRecord.forToken(token);
if (r != null) {
final TaskRecord task = r.task;
- if (task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+ if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
if (task.stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
return r;
@@ -709,7 +712,7 @@
// Still have something resumed; can't sleep until it is paused.
if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
- startPausingLocked(false, true);
+ startPausingLocked(false, true, false, false);
return true;
}
if (mPausingActivity != null) {
@@ -787,22 +790,38 @@
return null;
}
- final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
+ /**
+ * Start pausing the currently resumed activity. It is an error to call this if there
+ * is already an activity being paused or there is no resumed activity.
+ *
+ * @param userLeaving True if this should result in an onUserLeaving to the current activity.
+ * @param uiSleeping True if this is happening with the user interface going to sleep (the
+ * screen turning off).
+ * @param resuming True if this is being called as part of resuming the top activity, so
+ * we shouldn't try to instigate a resume here.
+ * @param dontWait True if the caller does not want to wait for the pause to complete. If
+ * set to true, we will immediately complete the pause here before returning.
+ * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
+ * it to tell us when it is done.
+ */
+ final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
+ boolean dontWait) {
if (mPausingActivity != null) {
- Slog.e(TAG, "Trying to pause when pause is already pending for "
- + mPausingActivity, new RuntimeException("here").fillInStackTrace());
+ Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
+ completePauseLocked(false);
}
ActivityRecord prev = mResumedActivity;
if (prev == null) {
- Slog.e(TAG, "Trying to pause when nothing is resumed",
- new RuntimeException("here").fillInStackTrace());
- mStackSupervisor.resumeTopActivitiesLocked();
- return;
+ if (!resuming) {
+ Slog.wtf(TAG, "Trying to pause when nothing is resumed");
+ mStackSupervisor.resumeTopActivitiesLocked();
+ }
+ return false;
}
if (mActivityContainer.mParentActivity == null) {
// Top level stack, not a child. Look for child stacks.
- mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping);
+ mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
}
if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
@@ -831,7 +850,7 @@
prev.shortComponentName);
mService.updateUsageStats(prev, false);
prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
- userLeaving, prev.configChangeFlags);
+ userLeaving, prev.configChangeFlags, dontWait);
} catch (Exception e) {
// Ignore exception, if process died other code will cleanup.
Slog.w(TAG, "Exception thrown during pause", e);
@@ -862,39 +881,46 @@
if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
}
- // Schedule a pause timeout in case the app doesn't respond.
- // We don't give it much time because this directly impacts the
- // responsiveness seen by the user.
- Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
- msg.obj = prev;
- prev.pauseTime = SystemClock.uptimeMillis();
- mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
- if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
+ if (dontWait) {
+ // If the caller said they don't want to wait for the pause, then complete
+ // the pause now.
+ completePauseLocked(false);
+ return false;
+
+ } else {
+ // Schedule a pause timeout in case the app doesn't respond.
+ // We don't give it much time because this directly impacts the
+ // responsiveness seen by the user.
+ Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
+ msg.obj = prev;
+ prev.pauseTime = SystemClock.uptimeMillis();
+ mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
+ if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
+ return true;
+ }
+
} else {
// This activity failed to schedule the
// pause, so just treat it as being paused now.
if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
- mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
+ if (!resuming) {
+ mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
+ }
+ return false;
}
}
- final void activityPausedLocked(IBinder token, boolean timeout,
- PersistableBundle persistentState) {
+ final void activityPausedLocked(IBinder token, boolean timeout) {
if (DEBUG_PAUSE) Slog.v(
TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
final ActivityRecord r = isInStackLocked(token);
if (r != null) {
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
- if (persistentState != null) {
- r.persistentState = persistentState;
- mService.notifyTaskPersisterLocked(r.task, false);
- }
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
- r.state = ActivityState.PAUSED;
- completePauseLocked();
+ completePauseLocked(true);
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
r.userId, System.identityHashCode(r), r.shortComponentName,
@@ -945,11 +971,12 @@
}
}
- private void completePauseLocked() {
+ private void completePauseLocked(boolean resumeNext) {
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
if (prev != null) {
+ prev.state = ActivityState.PAUSED;
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
@@ -992,19 +1019,21 @@
mPausingActivity = null;
}
- final ActivityStack topStack = mStackSupervisor.getFocusedStack();
- if (!mService.isSleepingOrShuttingDown()) {
- mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
- } else {
- mStackSupervisor.checkReadyForSleepLocked();
- ActivityRecord top = topStack.topRunningActivityLocked(null);
- if (top == null || (prev != null && top != prev)) {
- // If there are no more activities available to run,
- // do resume anyway to start something. Also if the top
- // activity on the stack is not the just paused activity,
- // we need to go ahead and resume it to ensure we complete
- // an in-flight app switch.
- mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
+ if (resumeNext) {
+ final ActivityStack topStack = mStackSupervisor.getFocusedStack();
+ if (!mService.isSleepingOrShuttingDown()) {
+ mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
+ } else {
+ mStackSupervisor.checkReadyForSleepLocked();
+ ActivityRecord top = topStack.topRunningActivityLocked(null);
+ if (top == null || (prev != null && top != prev)) {
+ // If there are no more activities available to run,
+ // do resume anyway to start something. Also if the top
+ // activity on the stack is not the just paused activity,
+ // we need to go ahead and resume it to ensure we complete
+ // an in-flight app switch.
+ mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
+ }
}
}
@@ -1439,6 +1468,23 @@
}
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
+ if (inResumeTopActivity) {
+ // Don't even start recursing.
+ return false;
+ }
+
+ boolean result = false;
+ try {
+ // Protect against recursion.
+ inResumeTopActivity = true;
+ result = resumeTopActivityInnerLocked(prev, options);
+ } finally {
+ inResumeTopActivity = false;
+ }
+ return result;
+ }
+
+ final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
ActivityRecord parent = mActivityContainer.mParentActivity;
@@ -1587,10 +1633,10 @@
// We need to start pausing the current activity so the top one
// can be resumed...
- boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
+ boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
+ boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
if (mResumedActivity != null) {
- pausing = true;
- startPausingLocked(userLeaving, false);
+ pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
}
if (pausing) {
@@ -2700,7 +2746,7 @@
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
- startPausingLocked(false, false);
+ startPausingLocked(false, false, false, false);
}
if (endTask) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 780efa1..b8261a4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -592,7 +592,7 @@
* @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
* @return true if any activity was paused as a result of this call.
*/
- boolean pauseBackStacks(boolean userLeaving) {
+ boolean pauseBackStacks(boolean userLeaving, boolean resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -601,8 +601,8 @@
if (!isFrontStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
- stack.startPausingLocked(userLeaving, false);
- someActivityPaused = true;
+ someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
+ dontWait);
}
}
}
@@ -631,7 +631,8 @@
return pausing;
}
- void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping) {
+ void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping,
+ boolean resuming, boolean dontWait) {
// TODO: Put all stacks in supervisor and iterate through them instead.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
@@ -639,7 +640,7 @@
final ActivityStack stack = stacks.get(stackNdx);
if (stack.mResumedActivity != null &&
stack.mActivityContainer.mParentActivity == parent) {
- stack.startPausingLocked(userLeaving, uiSleeping);
+ stack.startPausingLocked(userLeaving, uiSleeping, resuming, dontWait);
}
}
}
@@ -1640,57 +1641,8 @@
}
}
- if (sourceRecord == null) {
- // This activity is not being started from another... in this
- // case we -always- start a new task.
- if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
- Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
- "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
- launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
- }
- } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
- // The original activity who is starting us is running as a single
- // instance... this new activity it is starting must go on its
- // own task.
- launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
- } else if (launchSingleInstance || launchSingleTask) {
- // The activity being started is a single instance... it always
- // gets launched into its own task.
- launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
- }
-
- ActivityInfo newTaskInfo = null;
- Intent newTaskIntent = null;
- ActivityStack sourceStack;
- if (sourceRecord != null) {
- if (sourceRecord.finishing) {
- // If the source is finishing, we can't further count it as our source. This
- // is because the task it is associated with may now be empty and on its way out,
- // so we don't want to blindly throw it in to that task. Instead we will take
- // the NEW_TASK flow and try to find a task for it. But save the task information
- // so it can be used when creating the new task.
- if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
- Slog.w(TAG, "startActivity called from finishing " + sourceRecord
- + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
- launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
- newTaskInfo = sourceRecord.info;
- newTaskIntent = sourceRecord.task.intent;
- }
- sourceRecord = null;
- sourceStack = null;
- } else {
- sourceStack = sourceRecord.task.stack;
- }
- } else {
- sourceStack = null;
- }
-
boolean addingToTask = false;
- boolean movedHome = false;
TaskRecord reuseTask = null;
- ActivityStack targetStack;
-
- intent.setFlags(launchFlags);
// If the caller is not coming from another activity, but has given us an
// explicit task into which they would like us to launch the new activity,
@@ -1746,6 +1698,58 @@
inTask = null;
}
+ if (inTask == null) {
+ if (sourceRecord == null) {
+ // This activity is not being started from another... in this
+ // case we -always- start a new task.
+ if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
+ Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
+ "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
+ launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+ }
+ } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
+ // The original activity who is starting us is running as a single
+ // instance... this new activity it is starting must go on its
+ // own task.
+ launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+ } else if (launchSingleInstance || launchSingleTask) {
+ // The activity being started is a single instance... it always
+ // gets launched into its own task.
+ launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+ }
+ }
+
+ ActivityInfo newTaskInfo = null;
+ Intent newTaskIntent = null;
+ ActivityStack sourceStack;
+ if (sourceRecord != null) {
+ if (sourceRecord.finishing) {
+ // If the source is finishing, we can't further count it as our source. This
+ // is because the task it is associated with may now be empty and on its way out,
+ // so we don't want to blindly throw it in to that task. Instead we will take
+ // the NEW_TASK flow and try to find a task for it. But save the task information
+ // so it can be used when creating the new task.
+ if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
+ Slog.w(TAG, "startActivity called from finishing " + sourceRecord
+ + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
+ launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+ newTaskInfo = sourceRecord.info;
+ newTaskIntent = sourceRecord.task.intent;
+ }
+ sourceRecord = null;
+ sourceStack = null;
+ } else {
+ sourceStack = sourceRecord.task.stack;
+ }
+ } else {
+ sourceStack = null;
+ }
+
+ boolean movedHome = false;
+ ActivityStack targetStack;
+
+ intent.setFlags(launchFlags);
+
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
// this if NEW_TASK has been requested, and there is not an additional qualifier telling
@@ -1768,7 +1772,7 @@
if (intentActivity != null) {
if (isLockTaskModeViolation(intentActivity.task)) {
showLockTaskToast();
- Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+ Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (r.task == null) {
@@ -2779,9 +2783,8 @@
}
// A non-top activity is reporting a visibility change.
- if ((visible && (top.fullscreen || top.state != ActivityState.RESUMED)) ||
- top.app == null || top.app.thread == null) {
- // Can't carry out this request.
+ if (visible && top.fullscreen) {
+ // Let the caller know that it can't be seen.
if (DEBUG_VISIBLE_BEHIND) Slog.d(TAG, "requestVisibleBehind: returning top.fullscreen="
+ top.fullscreen + " top.state=" + top.state + " top.app=" + top.app +
" top.app.thread=" + top.app.thread);
@@ -2803,9 +2806,12 @@
mService.convertFromTranslucent(next.appToken);
}
}
- try {
- top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
- } catch (RemoteException e) {
+ if (top.app != null && top.app.thread != null) {
+ // Notify the top app of the change.
+ try {
+ top.app.thread.scheduleBackgroundVisibleBehindChanged(top.appToken, visible);
+ } catch (RemoteException e) {
+ }
}
return true;
}
@@ -3840,7 +3846,7 @@
mContainerState = CONTAINER_STATE_NO_SURFACE;
((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
- mStack.startPausingLocked(false, true);
+ mStack.startPausingLocked(false, true, false, false);
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 5a97aee..bba786d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -47,6 +47,7 @@
public final NetworkMonitor networkMonitor;
public final NetworkMisc networkMisc;
public boolean created;
+ public boolean validated;
// The list of NetworkRequests being satisfied by this Network.
public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
@@ -68,6 +69,7 @@
networkMonitor = new NetworkMonitor(context, handler, this);
networkMisc = misc;
created = false;
+ validated = false;
}
public void addRequest(NetworkRequest networkRequest) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index ff319d3..96872a7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -27,6 +27,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.TrafficStats;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -140,34 +141,28 @@
private static final int CMD_REEVALUATE = BASE + 6;
/**
- * Message to self indicating network evaluation is complete.
- * arg1 = Token to ignore old messages.
- * arg2 = HTTP response code of network evaluation.
- */
- private static final int EVENT_REEVALUATION_COMPLETE = BASE + 7;
-
- /**
* Inform NetworkMonitor that the network has disconnected.
*/
- public static final int CMD_NETWORK_DISCONNECTED = BASE + 8;
+ public static final int CMD_NETWORK_DISCONNECTED = BASE + 7;
/**
* Force evaluation even if it has succeeded in the past.
+ * arg1 = UID responsible for requesting this reeval. Will be billed for data.
*/
- public static final int CMD_FORCE_REEVALUATION = BASE + 9;
+ public static final int CMD_FORCE_REEVALUATION = BASE + 8;
/**
* Message to self indicating captive portal login is complete.
* arg1 = Token to ignore old messages.
* arg2 = 1 if we should use this network, 0 otherwise.
*/
- private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 10;
+ private static final int CMD_CAPTIVE_PORTAL_LOGGED_IN = BASE + 9;
/**
* Message to self indicating user desires to log into captive portal.
* arg1 = Token to ignore old messages.
*/
- private static final int CMD_USER_WANTS_SIGN_IN = BASE + 11;
+ private static final int CMD_USER_WANTS_SIGN_IN = BASE + 10;
/**
* Request ConnectivityService display provisioning notification.
@@ -175,22 +170,22 @@
* arg2 = NetID.
* obj = Intent to be launched when notification selected by user, null if !arg1.
*/
- public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 12;
+ public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 11;
/**
* Message to self indicating sign-in app bypassed captive portal.
*/
- private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 13;
+ private static final int EVENT_APP_BYPASSED_CAPTIVE_PORTAL = BASE + 12;
/**
* Message to self indicating no sign-in app responded.
*/
- private static final int EVENT_NO_APP_RESPONSE = BASE + 14;
+ private static final int EVENT_NO_APP_RESPONSE = BASE + 13;
/**
* Message to self indicating sign-in app indicates sign-in is not possible.
*/
- private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 15;
+ private static final int EVENT_APP_INDICATES_SIGN_IN_IMPOSSIBLE = BASE + 14;
private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger";
// Default to 30s linger time-out.
@@ -205,6 +200,8 @@
private static final int MAX_RETRIES = 10;
private final int mReevaluateDelayMs;
private int mReevaluateToken = 0;
+ private static final int INVALID_UID = -1;
+ private int mUidResponsibleForReeval = INVALID_UID;
private int mCaptivePortalLoggedInToken = 0;
private int mUserPromptedToken = 0;
@@ -282,6 +279,7 @@
return HANDLED;
case CMD_FORCE_REEVALUATION:
if (DBG) log("Forcing reevaluation");
+ mUidResponsibleForReeval = message.arg1;
transitionTo(mEvaluatingState);
return HANDLED;
default:
@@ -322,20 +320,14 @@
private class EvaluatingState extends State {
private int mRetries;
- private class EvaluateInternetConnectivity extends Thread {
- private int mToken;
- EvaluateInternetConnectivity(int token) {
- mToken = token;
- }
- public void run() {
- sendMessage(EVENT_REEVALUATION_COMPLETE, mToken, isCaptivePortal());
- }
- }
-
@Override
public void enter() {
mRetries = 0;
sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
+ if (mUidResponsibleForReeval != INVALID_UID) {
+ TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
+ mUidResponsibleForReeval = INVALID_UID;
+ }
}
@Override
@@ -356,14 +348,7 @@
transitionTo(mValidatedState);
return HANDLED;
}
- // Kick off a thread to perform internet connectivity evaluation.
- Thread thread = new EvaluateInternetConnectivity(mReevaluateToken);
- thread.run();
- return HANDLED;
- case EVENT_REEVALUATION_COMPLETE:
- if (message.arg1 != mReevaluateToken)
- return HANDLED;
- int httpResponseCode = message.arg2;
+ int httpResponseCode = isCaptivePortal();
if (httpResponseCode == 204) {
transitionTo(mValidatedState);
} else if (httpResponseCode >= 200 && httpResponseCode <= 399) {
@@ -375,10 +360,18 @@
sendMessageDelayed(msg, mReevaluateDelayMs);
}
return HANDLED;
+ case CMD_FORCE_REEVALUATION:
+ // Ignore duplicate requests.
+ return HANDLED;
default:
return NOT_HANDLED;
}
}
+
+ @Override
+ public void exit() {
+ TrafficStats.clearThreadStatsUid();
+ }
}
private class UserPromptedState extends State {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 9e169d9..f6beb9a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -46,6 +46,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCacheListener;
@@ -3098,26 +3099,28 @@
return;
}
+ UserHandle user = new UserHandle(userId);
final PendingIntent pendingIntent = PendingIntent
.getActivityAsUser(mContext, 0, clickIntent,
- PendingIntent.FLAG_CANCEL_CURRENT, null, new UserHandle(userId));
+ PendingIntent.FLAG_CANCEL_CURRENT, null, user);
CharSequence tooManyDeletesDescFormat = mContext.getResources().getText(
R.string.contentServiceTooManyDeletesNotificationDesc);
+ Context contextForUser = getContextForUser(user);
Notification notification =
new Notification(R.drawable.stat_notify_sync_error,
mContext.getString(R.string.contentServiceSync),
System.currentTimeMillis());
- notification.color = mContext.getResources().getColor(
+ notification.color = contextForUser.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color);
- notification.setLatestEventInfo(mContext,
- mContext.getString(R.string.contentServiceSyncNotificationTitle),
+ notification.setLatestEventInfo(contextForUser,
+ contextForUser.getString(R.string.contentServiceSyncNotificationTitle),
String.format(tooManyDeletesDescFormat.toString(), authorityName),
pendingIntent);
notification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
- notification, new UserHandle(userId));
+ notification, user);
}
/**
@@ -3305,4 +3308,13 @@
return mTable.size();
}
}
+
+ private Context getContextForUser(UserHandle user) {
+ try {
+ return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
+ } catch (NameNotFoundException e) {
+ // Default to mContext, not finding the package system is running as is unlikely.
+ return mContext;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index aa1310d..6ce235b 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -159,6 +159,8 @@
static final int TRUE = 1;
static final int FALSE = 0;
+ // Internal abort error code. It's the same as success.
+ static final int ABORT_NO_ERROR = -1;
// Constants related to operands of HDMI CEC commands.
// Refer to CEC Table 29 in HDMI Spec v1.4b.
// [Abort Reason]
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index bb22b4d..c5a6dbd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -31,8 +31,6 @@
import libcore.util.EmptyArray;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -102,11 +100,6 @@
// Stores the local CEC devices in the system. Device type is used for key.
private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>();
- @IoThreadOnly
- private final HdmiLogger mIoThreadLogger = new HdmiLogger(TAG);
- @ServiceThreadOnly
- private final HdmiLogger mServiceThreadLogger = new HdmiLogger(TAG);
-
// Private constructor. Use HdmiCecController.create().
private HdmiCecController(HdmiControlService service) {
mService = service;
@@ -210,9 +203,8 @@
}
final int assignedAddress = logicalAddress;
- mIoThreadLogger.debug(
- String.format("New logical address for device [%d]: [preferred:%d, assigned:%d]",
- deviceType, preferredAddress, assignedAddress));
+ HdmiLogger.debug("New logical address for device [%d]: [preferred:%d, assigned:%d]",
+ deviceType, preferredAddress, assignedAddress);
if (callback != null) {
runOnServiceThread(new Runnable() {
@Override
@@ -449,7 +441,7 @@
allocated.add(address);
}
}
- mIoThreadLogger.debug("[P]:Allocated Address=" + allocated);
+ HdmiLogger.debug("[P]:Allocated Address=" + allocated);
if (callback != null) {
runOnServiceThread(new Runnable() {
@Override
@@ -551,7 +543,7 @@
runOnIoThread(new Runnable() {
@Override
public void run() {
- mIoThreadLogger.debug("[S]:" + cecMessage);
+ HdmiLogger.debug("[S]:" + cecMessage);
byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
int i = 0;
int errorCode = Constants.SEND_RESULT_SUCCESS;
@@ -586,7 +578,7 @@
private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
assertRunOnServiceThread();
HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
- mServiceThreadLogger.debug("[R]:" + command);
+ HdmiLogger.debug("[R]:" + command);
onReceiveCommand(command);
}
@@ -596,8 +588,7 @@
@ServiceThreadOnly
private void handleHotplug(int port, boolean connected) {
assertRunOnServiceThread();
- mServiceThreadLogger.debug(
- "Hotplug event:[port:" + port + " , connected:" + connected + "]");
+ HdmiLogger.debug("Hotplug event:[port:%d, connected:%b]", port, connected);
mService.onHotplug(port, connected);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
index 85f5be2..b2300a6 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecFeatureAction.java
@@ -43,9 +43,6 @@
*/
abstract class HdmiCecFeatureAction {
private static final String TAG = "HdmiCecFeatureAction";
- // As all actions run in the same thread (service thread), it's fine to have single logger.
- // TODO: create global logger for each threads and use them.
- protected static final HdmiLogger DLOGGER = new HdmiLogger(TAG);
// Timer handler message used for timeout event
protected static final int MSG_TIMEOUT = 100;
@@ -264,10 +261,7 @@
}
protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) {
- sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(
- getSourceAddress(), targetAddress, uiCommand));
- sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
- getSourceAddress(), targetAddress));
+ mSource.sendUserControlPressedAndReleased(targetAddress, uiCommand);
}
protected final void addOnFinishedCallback(HdmiCecFeatureAction action, Runnable runnable) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index bc6a299..c00c5d0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -274,6 +274,12 @@
return handleRecordTvScreen(message);
case Constants.MESSAGE_TIMER_CLEARED_STATUS:
return handleTimerClearedStatus(message);
+ case Constants.MESSAGE_REPORT_POWER_STATUS:
+ return handleReportPowerStatus(message);
+ case Constants.MESSAGE_TIMER_STATUS:
+ return handleTimerStatus(message);
+ case Constants.MESSAGE_RECORD_STATUS:
+ return handleRecordStatus(message);
default:
return false;
}
@@ -541,6 +547,18 @@
return false;
}
+ protected boolean handleReportPowerStatus(HdmiCecMessage message) {
+ return false;
+ }
+
+ protected boolean handleTimerStatus(HdmiCecMessage message) {
+ return false;
+ }
+
+ protected boolean handleRecordStatus(HdmiCecMessage message) {
+ return false;
+ }
+
@ServiceThreadOnly
final void handleAddressAllocated(int logicalAddress, int reason) {
assertRunOnServiceThread();
@@ -810,6 +828,13 @@
Slog.w(TAG, "sendKeyEvent not implemented");
}
+ void sendUserControlPressedAndReleased(int targetAddress, int cecKeycode) {
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlPressed(
+ mAddress, targetAddress, cecKeycode));
+ mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+ mAddress, targetAddress));
+ }
+
/**
* Dump internal status of HdmiCecLocalDevice object.
*/
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 7ae2198..58ccbdb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -120,8 +120,6 @@
// other CEC devices since they might not have logical address.
private final ArraySet<Integer> mCecSwitches = new ArraySet<Integer>();
- private final HdmiLogger mSafeLogger = new HdmiLogger(TAG);
-
HdmiCecLocalDeviceTv(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_TV);
mPrevPortId = Constants.INVALID_PORT_ID;
@@ -476,6 +474,25 @@
return true;
}
+ @Override
+ protected boolean handleReportPowerStatus(HdmiCecMessage command) {
+ int newStatus = command.getParams()[0] & 0xFF;
+ updateDevicePowerStatus(command.getSource(), newStatus);
+ return true;
+ }
+
+ @Override
+ protected boolean handleTimerStatus(HdmiCecMessage message) {
+ // Do nothing.
+ return true;
+ }
+
+ @Override
+ protected boolean handleRecordStatus(HdmiCecMessage message) {
+ // Do nothing.
+ return true;
+ }
+
boolean updateCecSwitchInfo(int address, int type, int path) {
if (address == Constants.ADDR_UNREGISTERED
&& type == HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH) {
@@ -700,8 +717,7 @@
// # Seq 25
void setSystemAudioMode(boolean on, boolean updateSetting) {
- mSafeLogger.debug(String.format("System Audio Mode change[old:%b new:%b]",
- mSystemAudioActivated, on));
+ HdmiLogger.debug("System Audio Mode change[old:%b new:%b]", mSystemAudioActivated, on);
if (updateSetting) {
mService.writeBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, on);
@@ -832,6 +848,8 @@
AudioManager.STREAM_MUSIC);
mService.setAudioStatus(mute,
VolumeControlAction.scaleToCustomVolume(volume, maxVolume));
+ displayOsd(HdmiControlManager.OSD_MESSAGE_AVR_VOLUME_CHANGED,
+ mute ? HdmiControlManager.AVR_VOLUME_MUTED : volume);
}
}
@@ -855,12 +873,13 @@
}
}
- // Remove existing volume action.
- removeAction(VolumeControlAction.class);
-
- HdmiDeviceInfo avr = getAvrDeviceInfo();
- addAndStartAction(VolumeControlAction.ofVolumeChange(this, avr.getLogicalAddress(),
- cecVolume, delta > 0));
+ List<VolumeControlAction> actions = getActions(VolumeControlAction.class);
+ if (actions.isEmpty()) {
+ addAndStartAction(new VolumeControlAction(this,
+ getAvrDeviceInfo().getLogicalAddress(), delta > 0));
+ } else {
+ actions.get(0).handleVolumeChange(delta > 0);
+ }
}
@ServiceThreadOnly
@@ -872,8 +891,9 @@
// Remove existing volume action.
removeAction(VolumeControlAction.class);
- HdmiDeviceInfo avr = getAvrDeviceInfo();
- addAndStartAction(VolumeControlAction.ofMute(this, avr.getLogicalAddress(), mute));
+ sendUserControlPressedAndReleased(getAvrDeviceInfo().getLogicalAddress(),
+ mute ? HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION :
+ HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
}
@Override
@@ -935,8 +955,9 @@
protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
assertRunOnServiceThread();
if (!isMessageForSystemAudio(message)) {
- mSafeLogger.warning("Invalid <Set System Audio Mode> message:" + message);
- return false;
+ HdmiLogger.warning("Invalid <Set System Audio Mode> message:" + message);
+ mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+ return true;
}
SystemAudioActionFromAvr action = new SystemAudioActionFromAvr(this,
message.getSource(), HdmiUtils.parseCommandParamSystemAudioStatus(message), null);
@@ -949,8 +970,9 @@
protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) {
assertRunOnServiceThread();
if (!isMessageForSystemAudio(message)) {
- mSafeLogger.warning("Invalid <System Audio Mode Status> message:" + message);
- return false;
+ HdmiLogger.warning("Invalid <System Audio Mode Status> message:" + message);
+ // Ignore this message.
+ return true;
}
setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message), true);
return true;
@@ -973,7 +995,10 @@
int recorderAddress = message.getSource();
byte[] recordSource = mService.invokeRecordRequestListener(recorderAddress);
- startOneTouchRecord(recorderAddress, recordSource);
+ int reason = startOneTouchRecord(recorderAddress, recordSource);
+ if (reason != Constants.ABORT_NO_ERROR) {
+ mService.maySendFeatureAbortCommand(message, reason);
+ }
return true;
}
@@ -998,7 +1023,8 @@
}
private boolean isMessageForSystemAudio(HdmiCecMessage message) {
- return message.getSource() == Constants.ADDR_AUDIO_SYSTEM
+ return mService.isControlEnabled()
+ && message.getSource() == Constants.ADDR_AUDIO_SYSTEM
&& (message.getDestination() == Constants.ADDR_TV
|| message.getDestination() == Constants.ADDR_BROADCAST)
&& getAvrDeviceInfo() != null;
@@ -1445,31 +1471,38 @@
mService.displayOsd(messageId);
}
+ @ServiceThreadOnly
+ void displayOsd(int messageId, int extra) {
+ assertRunOnServiceThread();
+ mService.displayOsd(messageId, extra);
+ }
+
// Seq #54 and #55
@ServiceThreadOnly
- void startOneTouchRecord(int recorderAddress, byte[] recordSource) {
+ int startOneTouchRecord(int recorderAddress, byte[] recordSource) {
assertRunOnServiceThread();
if (!mService.isControlEnabled()) {
Slog.w(TAG, "Can not start one touch record. CEC control is disabled.");
announceOneTouchRecordResult(ONE_TOUCH_RECORD_CEC_DISABLED);
- return;
+ return Constants.ABORT_NOT_IN_CORRECT_MODE;
}
if (!checkRecorder(recorderAddress)) {
Slog.w(TAG, "Invalid recorder address:" + recorderAddress);
announceOneTouchRecordResult(ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
- return;
+ return Constants.ABORT_NOT_IN_CORRECT_MODE;
}
if (!checkRecordSource(recordSource)) {
Slog.w(TAG, "Invalid record source." + Arrays.toString(recordSource));
announceOneTouchRecordResult(ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN);
- return;
+ return Constants.ABORT_UNABLE_TO_DETERMINE;
}
addAndStartAction(new OneTouchRecordAction(this, recorderAddress, recordSource));
Slog.i(TAG, "Start new [One Touch Record]-Target:" + recorderAddress + ", recordSource:"
+ Arrays.toString(recordSource));
+ return Constants.ABORT_NO_ERROR;
}
@ServiceThreadOnly
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 8b345cf..0b3d9fb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -51,7 +51,6 @@
}
final SparseArray<ValidationInfo> mValidationInfo = new SparseArray<>();
- private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
public HdmiCecMessageValidator(HdmiControlService service) {
mService = service;
@@ -183,32 +182,32 @@
int opcode = message.getOpcode();
ValidationInfo info = mValidationInfo.get(opcode);
if (info == null) {
- mSpamSafeLogger.warning("No validation information for the message: " + message);
+ HdmiLogger.warning("No validation information for the message: " + message);
return true;
}
// Check the source field.
if (message.getSource() == Constants.ADDR_UNREGISTERED &&
(info.addressType & SRC_UNREGISTERED) == 0) {
- mSpamSafeLogger.warning("Unexpected source: " + message);
+ HdmiLogger.warning("Unexpected source: " + message);
return false;
}
// Check the destination field.
if (message.getDestination() == Constants.ADDR_BROADCAST) {
if ((info.addressType & DEST_BROADCAST) == 0) {
- mSpamSafeLogger.warning("Unexpected broadcast message: " + message);
+ HdmiLogger.warning("Unexpected broadcast message: " + message);
return false;
}
} else { // Direct addressing.
if ((info.addressType & DEST_DIRECT) == 0) {
- mSpamSafeLogger.warning("Unexpected direct message: " + message);
+ HdmiLogger.warning("Unexpected direct message: " + message);
return false;
}
}
// Check the parameter type.
if (!info.parameterValidator.isValid(message.getParams())) {
- mSpamSafeLogger.warning("Unexpected parameters: " + message);
+ HdmiLogger.warning("Unexpected parameters: " + message);
return false;
}
return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 6ba3fd1..5cd7c01 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -166,8 +166,6 @@
// Type of logical devices hosted in the system. Stored in the unmodifiable list.
private final List<Integer> mLocalDevices;
- private final HdmiLogger mSpamSafeLogger = new HdmiLogger(TAG);
-
// List of records for hotplug event listener to handle the the caller killed in action.
@GuardedBy("mLock")
private final ArrayList<HotplugEventListenerRecord> mHotplugEventListenerRecords =
@@ -656,7 +654,7 @@
if (mMessageValidator.isValid(command)) {
mCecController.sendCommand(command, callback);
} else {
- mSpamSafeLogger.error("Invalid message type:" + command);
+ HdmiLogger.error("Invalid message type:" + command);
if (callback != null) {
callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
}
@@ -705,7 +703,7 @@
}
if (message.getDestination() != Constants.ADDR_BROADCAST) {
- mSpamSafeLogger.warning("Unhandled cec command:" + message);
+ HdmiLogger.warning("Unhandled cec command:" + message);
}
return false;
}
@@ -794,7 +792,6 @@
// FLAG_HDMI_SYSTEM_AUDIO_VOLUME prevents audio manager from announcing
// volume change notification back to hdmi control service.
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume,
- AudioManager.FLAG_SHOW_UI |
AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME);
}
}
@@ -2033,4 +2030,14 @@
getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
HdmiControlService.PERMISSION);
}
+
+ @ServiceThreadOnly
+ void displayOsd(int messageId, int extra) {
+ assertRunOnServiceThread();
+ Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
+ intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
+ intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRAM_PARAM1, extra);
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
+ HdmiControlService.PERMISSION);
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index c7add75..2562ffc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -26,44 +26,83 @@
/**
* A logger that prevents spammy log. For the same log message, it logs once every 20seconds.
* This class is not thread-safe.
+ * <p>
+ * For convenience, use single character prefix for all messages.
+ * Here are common acronyms
+ * <ul>
+ * <li>[T]: Timout
+ * <li>[R]: Received message
+ * <li>[S]: Sent message
+ * <li>[P]: Device polling result
+ * </ul>
*/
final class HdmiLogger {
+ private static final String TAG = "HDMI";
// Logging duration for same error message.
private static final long ERROR_LOG_DURATTION_MILLIS = 20 * 1000; // 20s
private static final boolean DEBUG = false;
+ private static final ThreadLocal<HdmiLogger> sLogger = new ThreadLocal<>();
+
// Key (String): log message.
// Value (Pair(Long, Integer)): a pair of last log time millis and the number of logMessage.
// Cache for warning.
private final HashMap<String, Pair<Long, Integer>> mWarningTimingCache = new HashMap<>();
// Cache for error.
private final HashMap<String, Pair<Long, Integer>> mErrorTimingCache = new HashMap<>();
- private final String mTag;
- HdmiLogger(String tag) {
- mTag = "HDMI:" + tag;
+ private HdmiLogger() {
}
- void warning(String logMessage) {
+ static final void warning(String logMessage, Object... objs) {
+ getLogger().warningInternal(toLogString(logMessage, objs));
+ }
+
+ private void warningInternal(String logMessage) {
String log = updateLog(mWarningTimingCache, logMessage);
if (!log.isEmpty()) {
- Slog.w(mTag, log);
+ Slog.w(TAG, log);
}
}
- void error(String logMessage) {
+ static final void error(String logMessage, Object... objs) {
+ getLogger().errorInternal(toLogString(logMessage, objs));
+ }
+
+ private void errorInternal(String logMessage) {
String log = updateLog(mErrorTimingCache, logMessage);
if (!log.isEmpty()) {
- Slog.e(mTag, log);
+ Slog.e(TAG, log);
}
}
- void debug(String logMessage) {
+ static final void debug(String logMessage, Object... objs) {
+ getLogger().debugInternal(toLogString(logMessage, objs));
+ }
+
+ private void debugInternal(String logMessage) {
if (!DEBUG) {
return;
}
- Slog.d(mTag, logMessage);
+ Slog.d(TAG, logMessage);
+ }
+
+ private static final String toLogString(String logMessage, Object[] objs) {
+ if (objs.length > 0) {
+ return String.format(logMessage, objs);
+ } else {
+ return logMessage;
+ }
+ }
+
+ private static HdmiLogger getLogger() {
+ HdmiLogger logger = sLogger.get();
+ if (logger == null) {
+ logger = new HdmiLogger();
+ sLogger.set(logger);
+ }
+ return logger;
}
private static String updateLog(HashMap<String, Pair<Long, Integer>> cache, String logMessage) {
diff --git a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
index 03fbb95..1e29fd6 100644
--- a/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
+++ b/services/core/java/com/android/server/hdmi/PowerStatusMonitorAction.java
@@ -77,7 +77,7 @@
// if no device exists for incoming message, hands it over to other actions.
return false;
}
- int newStatus = cmd.getParams()[0];
+ int newStatus = cmd.getParams()[0] & 0xFF;
updatePowerStatus(sourceAddress, newStatus, true);
return true;
}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 17c2d6c..3fb450f 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -85,6 +85,7 @@
if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
return;
}
+ HdmiLogger.debug("[T]RequestArcAction.");
disableArcTransmission();
finish();
}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
index f25363d..d9e1f24 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -35,15 +35,15 @@
@Override
boolean start() {
+ mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+ addTimer(mState, HdmiConfig.TIMEOUT_MS);
+
HdmiCecMessage command = HdmiCecMessageBuilder.buildRequestArcInitiation(
getSourceAddress(), mAvrAddress);
sendCommand(command, new HdmiControlService.SendMessageCallback() {
@Override
public void onSendCompleted(int error) {
- if (error == Constants.SEND_RESULT_SUCCESS) {
- mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
- addTimer(mState, HdmiConfig.TIMEOUT_MS);
- } else {
+ if (error != Constants.SEND_RESULT_SUCCESS) {
// If failed to send <Request ARC Initiation>, start "Disabled"
// ARC transmission action.
disableArcTransmission();
diff --git a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
index 1491c72..f5a0115 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcTerminationAction.java
@@ -35,15 +35,15 @@
@Override
boolean start() {
+ mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
+ addTimer(mState, HdmiConfig.TIMEOUT_MS);
+
HdmiCecMessage command =
HdmiCecMessageBuilder.buildRequestArcTermination(getSourceAddress(), mAvrAddress);
sendCommand(command, new HdmiControlService.SendMessageCallback() {
@Override
public void onSendCompleted(int error) {
- if (error == Constants.SEND_RESULT_SUCCESS) {
- mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
- addTimer(mState, HdmiConfig.TIMEOUT_MS);
- } else {
+ if (error != Constants.SEND_RESULT_SUCCESS) {
// If failed to send <Request ARC Termination>, start "Disabled" ARC
// transmission action.
disableArcTransmission();
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 30519f3..bffa854 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -53,6 +53,18 @@
@Override
boolean start() {
if (mEnabled) {
+ // Enable ARC status immediately after sending <Report Arc Initiated>.
+ // If AVR responds with <Feature Abort>, disable ARC status again.
+ // This is different from spec that says that turns ARC status to
+ // "Enabled" if <Report ARC Initiated> is acknowledged and no
+ // <Feature Abort> is received.
+ // But implemented this way to save the time having to wait for
+ // <Feature Abort>.
+ setArcStatus(true);
+ // If succeeds to send <Report ARC Initiated>, wait general timeout
+ // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
+ mState = STATE_WAITING_TIMEOUT;
+ addTimer(mState, HdmiConfig.TIMEOUT_MS);
sendReportArcInitiated();
} else {
setArcStatus(false);
@@ -67,23 +79,11 @@
sendCommand(command, new HdmiControlService.SendMessageCallback() {
@Override
public void onSendCompleted(int error) {
- if (error == Constants.SEND_RESULT_SUCCESS) {
- // Enable ARC status immediately after sending <Report Arc Initiated>.
- // If AVR responds with <Feature Abort>, disable ARC status again.
- // This is different from spec that says that turns ARC status to
- // "Enabled" if <Report ARC Initiated> is acknowledged and no
- // <Feature Abort> is received.
- // But implemented this way to save the time having to wait for
- // <Feature Abort>.
- setArcStatus(true);
- // If succeeds to send <Report ARC Initiated>, wait general timeout
- // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
- mState = STATE_WAITING_TIMEOUT;
- addTimer(mState, HdmiConfig.TIMEOUT_MS);
- } else {
+ if (error != Constants.SEND_RESULT_SUCCESS) {
// If fails to send <Report ARC Initiated>, disable ARC and
// send <Report ARC Terminated> directly.
setArcStatus(false);
+ HdmiLogger.debug("Failed to send <Report Arc Initiated>.");
finish();
}
}
@@ -112,6 +112,7 @@
if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
int originalOpcode = cmd.getParams()[0] & 0xFF;
if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
+ HdmiLogger.debug("Feature aborted for <Report Arc Initiated>");
setArcStatus(false);
finish();
return true;
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index d15ffb0..0871194 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -98,7 +98,7 @@
@Override
public void onSendCompleted(int error) {
if (error != Constants.SEND_RESULT_SUCCESS) {
- DLOGGER.debug("Failed to send <System Audio Mode Request>:" + error);
+ HdmiLogger.debug("Failed to send <System Audio Mode Request>:" + error);
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED);
}
@@ -111,7 +111,7 @@
private void handleSendSystemAudioModeRequestTimeout() {
if (!mTargetAudioStatus // Don't retry for Off case.
|| mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
- DLOGGER.debug("[T]:wait for <Set System Audio Mode>.");
+ HdmiLogger.debug("[T]:wait for <Set System Audio Mode>.");
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_TIMEOUT);
return;
@@ -130,7 +130,7 @@
if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
&& (cmd.getParams()[0] & 0xFF)
== Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
- DLOGGER.debug("Failed to start system audio mode request.");
+ HdmiLogger.debug("Failed to start system audio mode request.");
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
return true;
@@ -145,7 +145,7 @@
startAudioStatusAction();
return true;
} else {
- DLOGGER.debug("Unexpected system audio mode request:" + receivedStatus);
+ HdmiLogger.debug("Unexpected system audio mode request:" + receivedStatus);
// Unexpected response, consider the request is newly initiated by AVR.
// To return 'false' will initiate new SystemAudioActionFromAvr by the control
// service.
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index ddc267a..4338fc7 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -17,66 +17,35 @@
package com.android.server.hdmi;
import static com.android.server.hdmi.Constants.IRT_MS;
+import static com.android.server.hdmi.Constants.MESSAGE_FEATURE_ABORT;
+import static com.android.server.hdmi.Constants.MESSAGE_REPORT_AUDIO_STATUS;
+import static com.android.server.hdmi.Constants.MESSAGE_USER_CONTROL_PRESSED;
-import com.android.internal.util.Preconditions;
+import android.media.AudioManager;
/**
* Feature action that transmits volume change to Audio Receiver.
* <p>
- * This action is created when a user pressed volume up/down. However, Since Android only provides a
- * listener for delta of some volume change, we will set a target volume, and check reported volume
- * from Audio Receiver(AVR). If TV receives no <Report Audio Status> from AVR, this action
- * will be finished in {@link #IRT_MS} * {@link #VOLUME_CHANGE_TIMEOUT_MAX_COUNT} (ms).
+ * This action is created when a user pressed volume up/down. However, Android only provides a
+ * listener for delta of some volume change instead of individual key event. Also it's hard to know
+ * Audio Receiver's number of volume steps for a single volume control key. Because of this, it
+ * sends key-down event until IRT timeout happens, and it will send key-up event if no additional
+ * volume change happens; otherwise, it will send again key-down as press and hold feature does.
*/
final class VolumeControlAction extends HdmiCecFeatureAction {
private static final String TAG = "VolumeControlAction";
- private static final int VOLUME_MUTE = 101;
- private static final int VOLUME_RESTORE = 102;
+ // State that wait for next volume press.
+ private static final int STATE_WAIT_FOR_NEXT_VOLUME_PRESS = 1;
private static final int MAX_VOLUME = 100;
- private static final int MIN_VOLUME = 0;
- // State where to wait for <Report Audio Status>
- private static final int STATE_WAIT_FOR_REPORT_VOLUME_STATUS = 1;
-
- // Maximum count of time out used to finish volume action.
- private static final int VOLUME_CHANGE_TIMEOUT_MAX_COUNT = 2;
+ private static final int UNKNOWN_AVR_VOLUME = -1;
private final int mAvrAddress;
- private final int mTargetVolume;
- private final boolean mIsVolumeUp;
- private int mTimeoutCount;
-
- /**
- * Create a {@link VolumeControlAction} for mute/restore change
- *
- * @param source source device sending volume change
- * @param avrAddress address of audio receiver
- * @param mute whether to mute sound or not. {@code true} for mute on; {@code false} for mute
- * off, i.e restore volume
- * @return newly created {@link VolumeControlAction}
- */
- public static VolumeControlAction ofMute(HdmiCecLocalDevice source, int avrAddress,
- boolean mute) {
- return new VolumeControlAction(source, avrAddress, mute ? VOLUME_MUTE : VOLUME_RESTORE,
- false);
- }
-
- /**
- * Create a {@link VolumeControlAction} for volume up/down change
- *
- * @param source source device sending volume change
- * @param avrAddress address of audio receiver
- * @param targetVolume target volume to be set to AVR. It should be in range of [0-100]
- * @param isVolumeUp whether to volume up or not. {@code true} for volume up; {@code false} for
- * volume down
- * @return newly created {@link VolumeControlAction}
- */
- public static VolumeControlAction ofVolumeChange(HdmiCecLocalDevice source, int avrAddress,
- int targetVolume, boolean isVolumeUp) {
- Preconditions.checkArgumentInRange(targetVolume, MIN_VOLUME, MAX_VOLUME, "volume");
- return new VolumeControlAction(source, avrAddress, targetVolume, isVolumeUp);
- }
+ private boolean mIsVolumeUp;
+ private long mLastKeyUpdateTime;
+ private int mLastAvrVolume;
+ private boolean mSentKeyPressed;
/**
* Scale a custom volume value to cec volume scale.
@@ -94,123 +63,141 @@
*
* @param cecVolume volume value in cec volume scale. It should be in a range of [0-100]
* @param scale scale of custom volume (max volume)
- * @return a volume value scaled to custom volume range
+ * @return a volume scaled to custom volume range
*/
public static int scaleToCustomVolume(int cecVolume, int scale) {
return (cecVolume * scale) / MAX_VOLUME;
}
- private VolumeControlAction(HdmiCecLocalDevice source, int avrAddress, int targetVolume,
- boolean isVolumeUp) {
+ VolumeControlAction(HdmiCecLocalDevice source, int avrAddress, boolean isVolumeUp) {
super(source);
-
mAvrAddress = avrAddress;
- mTargetVolume = targetVolume;
mIsVolumeUp = isVolumeUp;
+ mLastAvrVolume = UNKNOWN_AVR_VOLUME;
+ mSentKeyPressed = false;
+
+ updateLastKeyUpdateTime();
+ }
+
+ private void updateLastKeyUpdateTime() {
+ mLastKeyUpdateTime = System.currentTimeMillis();
}
@Override
boolean start() {
- if (isForMute()) {
- sendMuteChange(mTargetVolume == VOLUME_MUTE);
- finish();
- return true;
- }
-
- startVolumeChange();
+ mState = STATE_WAIT_FOR_NEXT_VOLUME_PRESS;
+ sendVolumeKeyPressed();
+ resetTimer();
return true;
}
-
- private boolean isForMute() {
- return mTargetVolume == VOLUME_MUTE || mTargetVolume == VOLUME_RESTORE;
- }
-
- private void startVolumeChange() {
- mTimeoutCount = 0;
- sendVolumeChange(mIsVolumeUp);
- mState = STATE_WAIT_FOR_REPORT_VOLUME_STATUS;
- addTimer(mState, IRT_MS);
- }
-
- private void sendVolumeChange(boolean up) {
+ private void sendVolumeKeyPressed() {
sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(), mAvrAddress,
- up ? HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
+ mIsVolumeUp ? HdmiCecKeycode.CEC_KEYCODE_VOLUME_UP
: HdmiCecKeycode.CEC_KEYCODE_VOLUME_DOWN));
+ mSentKeyPressed = true;
}
- private void sendMuteChange(boolean mute) {
- sendUserControlPressedAndReleased(mAvrAddress,
- mute ? HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION :
- HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION);
+ private void resetTimer() {
+ mActionTimer.clearTimerMessage();
+ addTimer(STATE_WAIT_FOR_NEXT_VOLUME_PRESS, IRT_MS);
+ }
+
+ void handleVolumeChange(boolean isVolumeUp) {
+ if (mIsVolumeUp != isVolumeUp) {
+ HdmiLogger.debug("Volume Key Status Changed[old:%b new:%b]", mIsVolumeUp, isVolumeUp);
+ sendVolumeKeyReleased();
+ mIsVolumeUp = isVolumeUp;
+ }
+ updateLastKeyUpdateTime();
+ }
+
+ private void sendVolumeKeyReleased() {
+ sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+ getSourceAddress(), mAvrAddress));
+ mSentKeyPressed = false;
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
- if (mState != STATE_WAIT_FOR_REPORT_VOLUME_STATUS) {
+ if (mState != STATE_WAIT_FOR_NEXT_VOLUME_PRESS || cmd.getSource() != mAvrAddress) {
return false;
}
switch (cmd.getOpcode()) {
- case Constants.MESSAGE_REPORT_AUDIO_STATUS:
- handleReportAudioStatus(cmd);
- return true;
- case Constants.MESSAGE_FEATURE_ABORT:
- int originalOpcode = cmd.getParams()[0] & 0xFF;
- if (originalOpcode == Constants.MESSAGE_USER_CONTROL_PRESSED
- || originalOpcode == Constants.MESSAGE_USER_CONTROL_RELEASED) {
- // TODO: handle feature abort.
- finish();
- return true;
- }
- default: // fall through
+ case MESSAGE_REPORT_AUDIO_STATUS:
+ return handleReportAudioStatus(cmd);
+ case MESSAGE_FEATURE_ABORT:
+ return handleFeatureAbort(cmd);
+ default:
return false;
}
}
- private void handleReportAudioStatus(HdmiCecMessage cmd) {
- byte[] params = cmd.getParams();
+ private boolean handleReportAudioStatus(HdmiCecMessage cmd) {
+ byte params[] = cmd.getParams();
+ boolean mute = (params[0] & 0x80) == 0x80;
int volume = params[0] & 0x7F;
- // Update volume with new value.
- // Note that it will affect system volume change.
- tv().setAudioStatus(false, volume);
- if (mIsVolumeUp) {
- if (mTargetVolume <= volume) {
- finishWithVolumeChangeRelease();
- return;
- }
- } else {
- if (mTargetVolume >= volume) {
- finishWithVolumeChangeRelease();
- return;
- }
+ mLastAvrVolume = volume;
+ if (shouldUpdateAudioVolume(mute)) {
+ HdmiLogger.debug("Force volume change[mute:%b, volume=%d]", mute, volume);
+ tv().setAudioStatus(mute, volume);
}
-
- // Clear action status and send another volume change command.
- clear();
- startVolumeChange();
+ return true;
}
- private void finishWithVolumeChangeRelease() {
- sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
- getSourceAddress(), mAvrAddress));
- finish();
+ private boolean shouldUpdateAudioVolume(boolean mute) {
+ // Do nothing if in mute.
+ if (mute) {
+ return true;
+ }
+
+ // Update audio status if current volume position is edge of volume bar,
+ // i.e max or min volume.
+ AudioManager audioManager = tv().getService().getAudioManager();
+ int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ if (mIsVolumeUp) {
+ int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ return currentVolume == maxVolume;
+ } else {
+ return currentVolume == 0;
+ }
+ }
+
+ private boolean handleFeatureAbort(HdmiCecMessage cmd) {
+ int originalOpcode = cmd.getParams()[0] & 0xFF;
+ // Since it sends <User Control Released> only when it finishes this action,
+ // it takes care of <User Control Pressed> only here.
+ if (originalOpcode == MESSAGE_USER_CONTROL_PRESSED) {
+ finish();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected void clear() {
+ super.clear();
+ if (mSentKeyPressed) {
+ sendVolumeKeyReleased();
+ }
+ if (mLastAvrVolume != UNKNOWN_AVR_VOLUME) {
+ tv().setAudioStatus(false, mLastAvrVolume);
+ mLastAvrVolume = UNKNOWN_AVR_VOLUME;
+ }
}
@Override
void handleTimerEvent(int state) {
- if (mState != STATE_WAIT_FOR_REPORT_VOLUME_STATUS) {
+ if (state != STATE_WAIT_FOR_NEXT_VOLUME_PRESS) {
return;
}
- // If no report volume action after IRT * VOLUME_CHANGE_TIMEOUT_MAX_COUNT just stop volume
- // action.
- if (++mTimeoutCount == VOLUME_CHANGE_TIMEOUT_MAX_COUNT) {
- finishWithVolumeChangeRelease();
- return;
+ if (System.currentTimeMillis() - mLastKeyUpdateTime >= IRT_MS) {
+ finish();
+ } else {
+ sendVolumeKeyPressed();
+ resetTimer();
}
-
- sendVolumeChange(mIsVolumeUp);
- addTimer(mState, IRT_MS);
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 93dceff..9c567ac 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -241,6 +241,9 @@
/** Switch code: Headphone/Microphone Jack. When set, something is inserted. */
public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
+ /** Switch code: Camera lens cover. When set the lens is covered. */
+ public static final int SW_CAMERA_LENS_COVER = 0x09;
+
public static final int SW_LID_BIT = 1 << SW_LID;
public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
@@ -249,6 +252,7 @@
public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
public static final int SW_JACK_BITS =
SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
+ public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
/** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
final boolean mUseDevInputEventForAudioJack;
@@ -693,7 +697,9 @@
synchronized (mDataStore) {
for (int i = 0; i < numFullKeyboards; i++) {
final InputDevice inputDevice = mTempFullKeyboards.get(i);
- if (mDataStore.getCurrentKeyboardLayout(inputDevice.getDescriptor()) == null) {
+ final String layout =
+ getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
+ if (layout == null) {
missingLayoutForExternalKeyboard = true;
if (i < numFullKeyboardsAdded) {
missingLayoutForExternalKeyboardAdded = true;
@@ -1380,6 +1386,11 @@
mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
}
+ if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
+ final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) == 0);
+ mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+ }
+
if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
switchMask);
@@ -1420,8 +1431,8 @@
}
// Native callback.
- private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
- return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
+ private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
whenNanos, policyFlags);
}
@@ -1575,6 +1586,8 @@
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
+
public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
public long notifyANR(InputApplicationHandle inputApplicationHandle,
@@ -1582,7 +1595,7 @@
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
- public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
+ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags);
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 2ef9828..11818d8 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -331,6 +331,7 @@
private int mSuplServerPort;
private String mC2KServerHost;
private int mC2KServerPort;
+ private boolean mSuplEsEnabled = false;
private final Context mContext;
private final NtpTrustedTime mNtpTime;
@@ -453,11 +454,10 @@
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
if (action.equals(ALARM_WAKEUP)) {
- if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
startNavigating(false);
} else if (action.equals(ALARM_TIMEOUT)) {
- if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
hibernate();
} else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
checkSmsSuplInit(intent);
@@ -494,6 +494,7 @@
Log.d(TAG, "SIM STATE is ready, SIM MCC/MNC is " + mccMnc);
synchronized (mLock) {
reloadGpsProperties(context, mProperties);
+ mNIHandler.setSuplEsEnablement(mSuplEsEnabled);
}
}
}
@@ -571,6 +572,16 @@
} catch (IOException ex) {
Log.w(TAG, "failed to dump properties contents");
}
+
+ // SUPL_ES configuration.
+ String suplESProperty = mProperties.getProperty("SUPL_ES");
+ if (suplESProperty != null) {
+ try {
+ mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
+ }
+ }
}
private void loadPropertiesFromResource(Context context,
@@ -612,7 +623,6 @@
mContext = context;
mNtpTime = NtpTrustedTime.getInstance(context);
mILocationManager = ilocationManager;
- mNIHandler = new GpsNetInitiatedHandler(context);
mLocation.setExtras(mLocationExtras);
@@ -639,6 +649,11 @@
mProperties = new Properties();
reloadGpsProperties(mContext, mProperties);
+ // Create a GPS net-initiated handler.
+ mNIHandler = new GpsNetInitiatedHandler(context,
+ mNetInitiatedListener,
+ mSuplEsEnabled);
+
// construct handler, listen for events
mHandler = new ProviderHandler(looper);
listenForBroadcasts();
@@ -691,7 +706,6 @@
intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
- intentFilter = new IntentFilter();
intentFilter.addAction(SIM_STATE_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b936130d..5097927 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -229,8 +229,14 @@
* {@link AudioManager#ADJUST_SAME}.
*
* @param direction The direction to adjust volume in.
+ * @param flags Any of the flags from {@link AudioManager}.
+ * @param packageName The package that made the original volume request.
+ * @param uid The uid that made the original volume request.
+ * @param useSuggested True to use adjustSuggestedStreamVolume instead of
+ * adjustStreamVolume.
*/
- public void adjustVolume(int direction, int flags, String packageName, int uid) {
+ public void adjustVolume(int direction, int flags, String packageName, int uid,
+ boolean useSuggested) {
if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
@@ -241,8 +247,13 @@
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
- mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
- uid);
+ if (useSuggested) {
+ mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction, flags,
+ packageName, uid);
+ } else {
+ mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags,
+ packageName, uid);
+ }
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
// Nothing to do, the volume cannot be changed
@@ -1020,7 +1031,7 @@
int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid);
+ MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid, false);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 0c6d46c..a12dd1c 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -814,7 +814,7 @@
}
} else {
session.adjustVolume(direction, flags, getContext().getPackageName(),
- UserHandle.myUserId());
+ UserHandle.myUserId(), true);
if (session.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE
&& mRvc != null) {
try {
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 189131c..05ad1fe 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -545,8 +545,9 @@
setZenModeCondition(condition, "downtime");
}
// exit downtime
- if (!inDowntime && mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
- && mDowntime.isDowntimeCondition(mExitCondition)) {
+ if (!inDowntime && mDowntime.isDowntimeCondition(mExitCondition)
+ && (mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ || mode == Global.ZEN_MODE_NO_INTERRUPTIONS)) {
mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "downtimeExit");
}
}
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
index 317ebef..b71bad8 100644
--- a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -43,6 +43,7 @@
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
+import java.util.TimeZone;
/** Built-in zen condition provider for managing downtime */
public class DowntimeConditionProvider extends ConditionProviderService {
@@ -275,6 +276,9 @@
final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
if (DEBUG) Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
action, ts(schTime), ts(now), now - schTime));
+ } else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
+ if (DEBUG) Slog.d(TAG, "timezone changed to " + TimeZone.getDefault());
+ mCalendar.setTimeZone(TimeZone.getDefault());
} else {
if (DEBUG) Slog.d(TAG, action + " fired at " + now);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0f4054..c09eff8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -49,6 +49,7 @@
import android.database.ContentObserver;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.AudioSystem;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
@@ -69,6 +70,7 @@
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.INotificationListener;
+import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
@@ -1126,6 +1128,19 @@
return mRankingHelper.getPackagePriority(pkg, uid);
}
+ @Override
+ public void setPackageVisibilityOverride(String pkg, int uid, int visibility) {
+ checkCallerIsSystem();
+ mRankingHelper.setPackageVisibilityOverride(pkg, uid, visibility);
+ savePolicyFile();
+ }
+
+ @Override
+ public int getPackageVisibilityOverride(String pkg, int uid) {
+ checkCallerIsSystem();
+ return mRankingHelper.getPackageVisibilityOverride(pkg, uid);
+ }
+
/**
* System-only API for getting a list of current (i.e. not cleared) notifications.
*
@@ -1457,7 +1472,14 @@
@Override
public boolean matchesCallFilter(Bundle extras) {
enforceSystemOrSystemUI("INotificationManager.matchesCallFilter");
- return mZenModeHelper.matchesCallFilter(extras,
+ return matchesCallFilterAsUser(extras, Binder.getCallingUid());
+ }
+
+ @Override
+ public boolean matchesCallFilterAsUser(Bundle extras, int userId) {
+ enforceSystemOrSystemUI("INotificationManager.matchesCallFilter");
+ UserHandle userHandle = new UserHandle(userId);
+ return mZenModeHelper.matchesCallFilter(userHandle, extras,
mRankingHelper.findExtractor(ValidateNotificationPeople.class));
}
};
@@ -1924,14 +1946,19 @@
}
private static AudioAttributes audioAttributesForNotification(Notification n) {
- if (n.audioAttributes != null
- && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) {
+ if (n.audioAttributes != null) {
return n.audioAttributes;
+ } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
+ // the stream type is valid, use it
+ return new AudioAttributes.Builder()
+ .setInternalLegacyStreamType(n.audioStreamType)
+ .build();
+ } else if (n.audioStreamType == AudioSystem.STREAM_DEFAULT) {
+ return Notification.AUDIO_ATTRIBUTES_DEFAULT;
+ } else {
+ Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+ return Notification.AUDIO_ATTRIBUTES_DEFAULT;
}
- return new AudioAttributes.Builder()
- .setLegacyStreamType(n.audioStreamType)
- .setUsage(AudioAttributes.usageForLegacyStreamType(n.audioStreamType))
- .build();
}
void showNextToastLocked() {
@@ -2045,12 +2072,15 @@
}
int indexBefore = findNotificationRecordIndexLocked(record);
boolean interceptBefore = record.isIntercepted();
+ int visibilityBefore = record.getPackageVisibilityOverride();
recon.applyChangesLocked(record);
applyZenModeLocked(record);
mRankingHelper.sort(mNotificationList);
int indexAfter = findNotificationRecordIndexLocked(record);
boolean interceptAfter = record.isIntercepted();
- changed = indexBefore != indexAfter || interceptBefore != interceptAfter;
+ int visibilityAfter = record.getPackageVisibilityOverride();
+ changed = indexBefore != indexAfter || interceptBefore != interceptAfter
+ || visibilityBefore != visibilityAfter;
if (interceptBefore && !interceptAfter) {
buzzBeepBlinkLocked(record);
}
@@ -2064,14 +2094,18 @@
synchronized (mNotificationList) {
final int N = mNotificationList.size();
ArrayList<String> orderBefore = new ArrayList<String>(N);
+ int[] visibilities = new int[N];
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
orderBefore.add(r.getKey());
+ visibilities[i] = r.getPackageVisibilityOverride();
mRankingHelper.extractSignals(r);
}
- mRankingHelper.sort(mNotificationList);
for (int i = 0; i < N; i++) {
- if (!orderBefore.get(i).equals(mNotificationList.get(i).getKey())) {
+ mRankingHelper.sort(mNotificationList);
+ final NotificationRecord r = mNotificationList.get(i);
+ if (!orderBefore.get(i).equals(r.getKey())
+ || visibilities[i] != r.getPackageVisibilityOverride()) {
scheduleSendRankingUpdate();
return;
}
@@ -2601,6 +2635,7 @@
final int N = mNotificationList.size();
ArrayList<String> keys = new ArrayList<String>(N);
ArrayList<String> interceptedKeys = new ArrayList<String>(N);
+ Bundle visibilityOverrides = new Bundle();
for (int i = 0; i < N; i++) {
NotificationRecord record = mNotificationList.get(i);
if (!isVisibleToListener(record.sbn, info)) {
@@ -2610,14 +2645,28 @@
if (record.isIntercepted()) {
interceptedKeys.add(record.sbn.getKey());
}
+ if (record.getPackageVisibilityOverride()
+ != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+ visibilityOverrides.putInt(record.sbn.getKey(),
+ record.getPackageVisibilityOverride());
+ }
+ // Find first min-prio notification for speedbump placement.
if (speedBumpIndex == -1 &&
+ // Intrusiveness trumps priority, hence ignore intrusives.
+ !record.isRecentlyIntrusive() &&
+ // Currently, package priority is either PRIORITY_DEFAULT or PRIORITY_MAX, so
+ // scanning for PRIORITY_MIN within the package bucket PRIORITY_DEFAULT
+ // (or lower as a safeguard) is sufficient to find the speedbump index.
+ // We'll have to revisit this when more package priority buckets are introduced.
+ record.getPackagePriority() <= Notification.PRIORITY_DEFAULT &&
record.sbn.getNotification().priority == Notification.PRIORITY_MIN) {
speedBumpIndex = keys.size() - 1;
}
}
String[] keysAr = keys.toArray(new String[keys.size()]);
String[] interceptedKeysAr = interceptedKeys.toArray(new String[interceptedKeys.size()]);
- return new NotificationRankingUpdate(keysAr, interceptedKeysAr, speedBumpIndex);
+ return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
+ speedBumpIndex);
}
private boolean isVisibleToListener(StatusBarNotification sbn, ManagedServiceInfo listener) {
@@ -2811,8 +2860,9 @@
private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
final INotificationListener listener = (INotificationListener)info.service;
+ StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
- listener.onNotificationPosted(sbn, rankingUpdate);
+ listener.onNotificationPosted(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
@@ -2824,8 +2874,9 @@
return;
}
final INotificationListener listener = (INotificationListener) info.service;
+ StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
- listener.onNotificationRemoved(sbn, rankingUpdate);
+ listener.onNotificationRemoved(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
}
@@ -2913,4 +2964,25 @@
return zen ? "zen" : ('\'' + pkgFilter + '\'');
}
}
+
+ /**
+ * Wrapper for a StatusBarNotification object that allows transfer across a oneway
+ * binder without sending large amounts of data over a oneway transaction.
+ */
+ private static final class StatusBarNotificationHolder
+ extends IStatusBarNotificationHolder.Stub {
+ private StatusBarNotification mValue;
+
+ public StatusBarNotificationHolder(StatusBarNotification value) {
+ mValue = value;
+ }
+
+ /** Get the held value and clear it. This function should only be called once per holder */
+ @Override
+ public StatusBarNotification get() {
+ StatusBarNotification value = mValue;
+ mValue = null;
+ return value;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index f2bd676..fd34aa5 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -21,6 +21,7 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.media.AudioAttributes;
+import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import com.android.internal.annotations.VisibleForTesting;
@@ -65,6 +66,7 @@
private int mAuthoritativeRank;
private String mGlobalSortKey;
+ private int mPackageVisibility;
@VisibleForTesting
public NotificationRecord(StatusBarNotification sbn, int score)
@@ -79,6 +81,7 @@
mContactAffinity = previous.mContactAffinity;
mRecentlyIntrusive = previous.mRecentlyIntrusive;
mPackagePriority = previous.mPackagePriority;
+ mPackageVisibility = previous.mPackageVisibility;
mIntercept = previous.mIntercept;
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
// Don't copy mGlobalSortKey, recompute it.
@@ -86,8 +89,10 @@
public Notification getNotification() { return sbn.getNotification(); }
public int getFlags() { return sbn.getNotification().flags; }
- public int getUserId() { return sbn.getUserId(); }
+ public UserHandle getUser() { return sbn.getUser(); }
public String getKey() { return sbn.getKey(); }
+ /** @deprecated Use {@link #getUser()} instead. */
+ public int getUserId() { return sbn.getUserId(); }
void dump(PrintWriter pw, String prefix, Context baseContext) {
final Notification notification = sbn.getNotification();
@@ -155,6 +160,7 @@
pw.println(prefix + " mContactAffinity=" + mContactAffinity);
pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive);
pw.println(prefix + " mPackagePriority=" + mPackagePriority);
+ pw.println(prefix + " mPackageVisibility=" + mPackageVisibility);
pw.println(prefix + " mIntercept=" + mIntercept);
pw.println(prefix + " mGlobalSortKey=" + mGlobalSortKey);
pw.println(prefix + " mRankingTimeMs=" + mRankingTimeMs);
@@ -216,6 +222,14 @@
return mPackagePriority;
}
+ public void setPackageVisibilityOverride(int packageVisibility) {
+ mPackageVisibility = packageVisibility;
+ }
+
+ public int getPackageVisibilityOverride() {
+ return mPackageVisibility;
+ }
+
public boolean setIntercepted(boolean intercept) {
mIntercept = intercept;
return mIntercept;
diff --git a/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java b/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java
new file mode 100644
index 0000000..f720f9f
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PackageVisibilityExtractor.java
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2014 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.notification;
+
+import android.content.Context;
+import android.util.Slog;
+
+public class PackageVisibilityExtractor implements NotificationSignalExtractor {
+ private static final String TAG = "PackageVisibilityExtractor";
+ private static final boolean DBG = false;
+
+ private RankingConfig mConfig;
+
+ public void initialize(Context ctx) {
+ if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
+ }
+
+ public RankingReconsideration process(NotificationRecord record) {
+ if (record == null || record.getNotification() == null) {
+ if (DBG) Slog.d(TAG, "skipping empty notification");
+ return null;
+ }
+
+ if (mConfig == null) {
+ if (DBG) Slog.d(TAG, "missing config");
+ return null;
+ }
+
+ final int packageVisibility = mConfig.getPackageVisibilityOverride(
+ record.sbn.getPackageName(), record.sbn.getUid());
+ record.setPackageVisibilityOverride(packageVisibility);
+
+ return null;
+ }
+
+ @Override
+ public void setConfig(RankingConfig config) {
+ mConfig = config;
+ }
+}
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 7d0bd59..aea137b 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -19,4 +19,8 @@
int getPackagePriority(String packageName, int uid);
void setPackagePriority(String packageName, int uid, int priority);
+
+ int getPackageVisibilityOverride(String packageName, int uid);
+
+ void setPackageVisibilityOverride(String packageName, int uid, int visibility);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 435177b..aeddecb 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -20,8 +20,10 @@
import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
+import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseIntArray;
@@ -33,7 +35,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
public class RankingHelper implements RankingConfig {
@@ -49,6 +51,7 @@
private static final String ATT_NAME = "name";
private static final String ATT_UID = "uid";
private static final String ATT_PRIORITY = "priority";
+ private static final String ATT_VISIBILITY = "visibility";
private final NotificationSignalExtractor[] mSignalExtractors;
private final NotificationComparator mPreliminaryComparator = new NotificationComparator();
@@ -56,6 +59,7 @@
// Package name to uid, to priority. Would be better as Table<String, Int, Int>
private final ArrayMap<String, SparseIntArray> mPackagePriorities;
+ private final ArrayMap<String, SparseIntArray> mPackageVisibilities;
private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp;
private final Context mContext;
@@ -65,6 +69,7 @@
mContext = context;
mRankingHandler = rankingHandler;
mPackagePriorities = new ArrayMap<String, SparseIntArray>();
+ mPackageVisibilities = new ArrayMap<String, SparseIntArray>();
final int N = extractorNames.length;
mSignalExtractors = new NotificationSignalExtractor[N];
@@ -132,15 +137,27 @@
if (TAG_PACKAGE.equals(tag)) {
int uid = safeInt(parser, ATT_UID, UserHandle.USER_ALL);
int priority = safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT);
+ int vis = safeInt(parser, ATT_VISIBILITY,
+ NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
String name = parser.getAttributeValue(null, ATT_NAME);
- if (!TextUtils.isEmpty(name) && priority != Notification.PRIORITY_DEFAULT) {
- SparseIntArray priorityByUid = mPackagePriorities.get(name);
- if (priorityByUid == null) {
- priorityByUid = new SparseIntArray();
- mPackagePriorities.put(name, priorityByUid);
+ if (!TextUtils.isEmpty(name)) {
+ if (priority != Notification.PRIORITY_DEFAULT) {
+ SparseIntArray priorityByUid = mPackagePriorities.get(name);
+ if (priorityByUid == null) {
+ priorityByUid = new SparseIntArray();
+ mPackagePriorities.put(name, priorityByUid);
+ }
+ priorityByUid.put(uid, priority);
}
- priorityByUid.put(uid, priority);
+ if (vis != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+ SparseIntArray visibilityByUid = mPackageVisibilities.get(name);
+ if (visibilityByUid == null) {
+ visibilityByUid = new SparseIntArray();
+ mPackageVisibilities.put(name, visibilityByUid);
+ }
+ visibilityByUid.put(uid, vis);
+ }
}
}
}
@@ -152,18 +169,43 @@
out.startTag(null, TAG_RANKING);
out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
- final int N = mPackagePriorities.size();
- for (int i = 0; i < N; i ++) {
- String name = mPackagePriorities.keyAt(i);
- SparseIntArray priorityByUid = mPackagePriorities.get(name);
- final int M = priorityByUid.size();
- for (int j = 0; j < M; j++) {
- int uid = priorityByUid.keyAt(j);
- int priority = priorityByUid.get(uid);
+ final Set<String> packageNames = new ArraySet<>(mPackagePriorities.size()
+ + mPackageVisibilities.size());
+ packageNames.addAll(mPackagePriorities.keySet());
+ packageNames.addAll(mPackageVisibilities.keySet());
+ final Set<Integer> packageUids = new ArraySet<>();
+ for (String packageName : packageNames) {
+ packageUids.clear();
+ SparseIntArray priorityByUid = mPackagePriorities.get(packageName);
+ SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+ if (priorityByUid != null) {
+ final int M = priorityByUid.size();
+ for (int j = 0; j < M; j++) {
+ packageUids.add(priorityByUid.keyAt(j));
+ }
+ }
+ if (visibilityByUid != null) {
+ final int M = visibilityByUid.size();
+ for (int j = 0; j < M; j++) {
+ packageUids.add(visibilityByUid.keyAt(j));
+ }
+ }
+ for (Integer uid : packageUids) {
out.startTag(null, TAG_PACKAGE);
- out.attribute(null, ATT_NAME, name);
+ out.attribute(null, ATT_NAME, packageName);
+ if (priorityByUid != null) {
+ final int priority = priorityByUid.get(uid);
+ if (priority != Notification.PRIORITY_DEFAULT) {
+ out.attribute(null, ATT_PRIORITY, Integer.toString(priority));
+ }
+ }
+ if (visibilityByUid != null) {
+ final int visibility = visibilityByUid.get(uid);
+ if (visibility != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
+ out.attribute(null, ATT_VISIBILITY, Integer.toString(visibility));
+ }
+ }
out.attribute(null, ATT_UID, Integer.toString(uid));
- out.attribute(null, ATT_PRIORITY, Integer.toString(priority));
out.endTag(null, TAG_PACKAGE);
}
}
@@ -293,6 +335,31 @@
updateConfig();
}
+ @Override
+ public int getPackageVisibilityOverride(String packageName, int uid) {
+ int visibility = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+ if (visibilityByUid != null) {
+ visibility = visibilityByUid.get(uid,
+ NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE);
+ }
+ return visibility;
+ }
+
+ @Override
+ public void setPackageVisibilityOverride(String packageName, int uid, int visibility) {
+ if (visibility == getPackageVisibilityOverride(packageName, uid)) {
+ return;
+ }
+ SparseIntArray visibilityByUid = mPackageVisibilities.get(packageName);
+ if (visibilityByUid == null) {
+ visibilityByUid = new SparseIntArray();
+ mPackageVisibilities.put(packageName, visibilityByUid);
+ }
+ visibilityByUid.put(uid, visibility);
+ updateConfig();
+ }
+
public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
if (filter == null) {
final int N = mSignalExtractors.length;
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index aa47858..f266916 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -18,18 +18,23 @@
import android.app.Notification;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.os.UserHandle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
import android.util.LruCache;
import android.util.Slog;
import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.Map;
/**
* This {@link NotificationSignalExtractor} attempts to validate
@@ -65,21 +70,88 @@
static final float STARRED_CONTACT = 1f;
protected boolean mEnabled;
- private Context mContext;
+ private Context mBaseContext;
// maps raw person handle to resolved person object
private LruCache<String, LookupResult> mPeopleCache;
+ private Map<Integer, Context> mUserToContextMap;
- private RankingReconsideration validatePeople(final NotificationRecord record) {
+ public void initialize(Context context) {
+ if (DEBUG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
+ mUserToContextMap = new ArrayMap<>();
+ mBaseContext = context;
+ mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
+ mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt(
+ mBaseContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
+ }
+
+ public RankingReconsideration process(NotificationRecord record) {
+ if (!mEnabled) {
+ if (INFO) Slog.i(TAG, "disabled");
+ return null;
+ }
+ if (record == null || record.getNotification() == null) {
+ if (INFO) Slog.i(TAG, "skipping empty notification");
+ return null;
+ }
+ if (record.getUserId() == UserHandle.USER_ALL) {
+ if (INFO) Slog.i(TAG, "skipping global notification");
+ return null;
+ }
+ Context context = getContextAsUser(record.getUser());
+ if (context == null) {
+ if (INFO) Slog.i(TAG, "skipping notification that lacks a context");
+ return null;
+ }
+ return validatePeople(context, record);
+ }
+
+ @Override
+ public void setConfig(RankingConfig config) {
+ // ignore: config has no relevant information yet.
+ }
+
+ public float getContactAffinity(UserHandle userHandle, Bundle extras) {
+ if (extras == null) return NONE;
+ final String key = Long.toString(System.nanoTime());
+ final float[] affinityOut = new float[1];
+ Context context = getContextAsUser(userHandle);
+ if (context == null) {
+ return NONE;
+ }
+ final PeopleRankingReconsideration prr = validatePeople(context, key, extras, affinityOut);
+ float affinity = affinityOut[0];
+ if (prr != null) {
+ prr.work();
+ affinity = Math.max(prr.getContactAffinity(), affinity);
+ }
+ return affinity;
+ }
+
+ private Context getContextAsUser(UserHandle userHandle) {
+ Context context = mUserToContextMap.get(userHandle.getIdentifier());
+ if (context == null) {
+ try {
+ context = mBaseContext.createPackageContextAsUser("android", 0, userHandle);
+ mUserToContextMap.put(userHandle.getIdentifier(), context);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "failed to create package context for lookups", e);
+ }
+ }
+ return context;
+ }
+
+ private RankingReconsideration validatePeople(Context context,
+ final NotificationRecord record) {
final String key = record.getKey();
final Bundle extras = record.getNotification().extras;
final float[] affinityOut = new float[1];
- final RankingReconsideration rr = validatePeople(key, extras, affinityOut);
+ final RankingReconsideration rr = validatePeople(context, key, extras, affinityOut);
record.setContactAffinity(affinityOut[0]);
return rr;
}
- private PeopleRankingReconsideration validatePeople(String key, Bundle extras,
+ private PeopleRankingReconsideration validatePeople(Context context, String key, Bundle extras,
float[] affinityOut) {
float affinity = NONE;
if (extras == null) {
@@ -98,7 +170,8 @@
if (TextUtils.isEmpty(handle)) continue;
synchronized (mPeopleCache) {
- LookupResult lookupResult = mPeopleCache.get(handle);
+ final String cacheKey = getCacheKey(context.getUserId(), handle);
+ LookupResult lookupResult = mPeopleCache.get(cacheKey);
if (lookupResult == null || lookupResult.isExpired()) {
pendingLookups.add(handle);
} else {
@@ -119,7 +192,11 @@
}
if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + key);
- return new PeopleRankingReconsideration(key, pendingLookups);
+ return new PeopleRankingReconsideration(context, key, pendingLookups);
+ }
+
+ private String getCacheKey(int userId, String handle) {
+ return Integer.toString(userId) + ":" + handle;
}
// VisibleForTesting
@@ -185,24 +262,24 @@
return null;
}
- private LookupResult resolvePhoneContact(final String number) {
+ private LookupResult resolvePhoneContact(Context context, final String number) {
Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(number));
- return searchContacts(phoneUri);
+ return searchContacts(context, phoneUri);
}
- private LookupResult resolveEmailContact(final String email) {
+ private LookupResult resolveEmailContact(Context context, final String email) {
Uri numberUri = Uri.withAppendedPath(
ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI,
Uri.encode(email));
- return searchContacts(numberUri);
+ return searchContacts(context, numberUri);
}
- private LookupResult searchContacts(Uri lookupUri) {
+ private LookupResult searchContacts(Context context, Uri lookupUri) {
LookupResult lookupResult = new LookupResult();
Cursor c = null;
try {
- c = mContext.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
+ c = context.getContentResolver().query(lookupUri, LOOKUP_PROJECTION, null, null, null);
if (c != null && c.getCount() > 0) {
c.moveToFirst();
lookupResult.readContact(c);
@@ -217,44 +294,6 @@
return lookupResult;
}
- public void initialize(Context context) {
- if (DEBUG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
- mContext = context;
- mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
- mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt(
- mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
- }
-
- public RankingReconsideration process(NotificationRecord record) {
- if (!mEnabled) {
- if (INFO) Slog.i(TAG, "disabled");
- return null;
- }
- if (record == null || record.getNotification() == null) {
- if (INFO) Slog.i(TAG, "skipping empty notification");
- return null;
- }
- return validatePeople(record);
- }
-
- @Override
- public void setConfig(RankingConfig config) {
- // ignore: config has no relevant information yet.
- }
-
- public float getContactAffinity(Bundle extras) {
- if (extras == null) return NONE;
- final String key = Long.toString(System.nanoTime());
- final float[] affinityOut = new float[1];
- final PeopleRankingReconsideration prr = validatePeople(key, extras, affinityOut);
- float affinity = affinityOut[0];
- if (prr != null) {
- prr.work();
- affinity = Math.max(prr.getContactAffinity(), affinity);
- }
- return affinity;
- }
-
private static class LookupResult {
private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
public static final int INVALID_ID = -1;
@@ -317,11 +356,13 @@
private class PeopleRankingReconsideration extends RankingReconsideration {
private final LinkedList<String> mPendingLookups;
+ private final Context mContext;
private float mContactAffinity = NONE;
- private PeopleRankingReconsideration(String key, LinkedList<String> pendingLookups) {
+ private PeopleRankingReconsideration(Context context, String key, LinkedList<String> pendingLookups) {
super(key);
+ mContext = context;
mPendingLookups = pendingLookups;
}
@@ -333,20 +374,21 @@
final Uri uri = Uri.parse(handle);
if ("tel".equals(uri.getScheme())) {
if (DEBUG) Slog.d(TAG, "checking telephone URI: " + handle);
- lookupResult = resolvePhoneContact(uri.getSchemeSpecificPart());
+ lookupResult = resolvePhoneContact(mContext, uri.getSchemeSpecificPart());
} else if ("mailto".equals(uri.getScheme())) {
if (DEBUG) Slog.d(TAG, "checking mailto URI: " + handle);
- lookupResult = resolveEmailContact(uri.getSchemeSpecificPart());
+ lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart());
} else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle);
- lookupResult = searchContacts(uri);
+ lookupResult = searchContacts(mContext, uri);
} else {
lookupResult = new LookupResult(); // invalid person for the cache
Slog.w(TAG, "unsupported URI " + handle);
}
if (lookupResult != null) {
synchronized (mPeopleCache) {
- mPeopleCache.put(handle, lookupResult);
+ final String cacheKey = getCacheKey(mContext.getUserId(), handle);
+ mPeopleCache.put(cacheKey, lookupResult);
}
mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity());
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index fd35ede..41d7fa8f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -18,7 +18,6 @@
import static android.media.AudioAttributes.USAGE_ALARM;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
-import static android.media.AudioAttributes.USAGE_UNKNOWN;
import android.app.AppOpsManager;
import android.app.Notification;
@@ -225,11 +224,6 @@
muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
exceptionPackages);
- // restrict vibrations with no hints
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_UNKNOWN,
- zen ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
-
// alarm restrictions
final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, USAGE_ALARM,
@@ -307,8 +301,8 @@
final int ringerMode = mAudioManager.getRingerMode();
int newZen = -1;
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS) {
- newZen = Global.ZEN_MODE_NO_INTERRUPTIONS;
+ if (mZenMode == Global.ZEN_MODE_OFF) {
+ newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
}
} else if ((ringerMode == AudioManager.RINGER_MODE_NORMAL
|| ringerMode == AudioManager.RINGER_MODE_VIBRATE)
@@ -373,13 +367,14 @@
return record.isCategory(Notification.CATEGORY_MESSAGE) || isDefaultMessagingApp(record);
}
- public boolean matchesCallFilter(Bundle extras, ValidateNotificationPeople validator) {
+ public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
+ ValidateNotificationPeople validator) {
final int zen = mZenMode;
if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through
if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
if (!mConfig.allowCalls) return false; // no calls get through
if (validator != null) {
- final float contactAffinity = validator.getContactAffinity(extras);
+ final float contactAffinity = validator.getContactAffinity(userHandle, extras);
return audienceMatches(contactAffinity);
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 355f34f..a7eebf8 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -75,7 +75,7 @@
schedule(BackgroundDexOptService.this);
return;
}
- pm.performDexOpt(pkg, null /* instruction set */, false);
+ pm.performDexOpt(pkg, null /* instruction set */, true);
}
// ran to completion, so we abandon our timeslice and do not reschedule
jobFinished(jobParams, false);
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b7b1c23..dcc4f8d 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -199,8 +199,7 @@
mainIntent.setPackage(packageName);
long ident = Binder.clearCallingIdentity();
try {
- List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
- PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user
+ List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0 /* flags */,
user.getIdentifier());
return apps;
} finally {
@@ -288,8 +287,7 @@
// as calling startActivityAsUser ignores the category and just
// resolves based on the component if present.
List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
- PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user
- user.getIdentifier());
+ 0 /* flags */, user.getIdentifier());
final int size = apps.size();
for (int i = 0; i < size; ++i) {
ActivityInfo activityInfo = apps.get(i).activityInfo;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 3f7a607..496c136 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -42,23 +42,18 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
-import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageInstaller;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.PackageInstaller;
-import android.content.pm.PackageParser;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
-import android.content.pm.PackageParser.PackageLite;
-import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Environment.UserEnvironment;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
@@ -70,7 +65,6 @@
import android.os.SELinux;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
@@ -126,6 +120,7 @@
private static final String ATTR_CREATED_MILLIS = "createdMillis";
private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
+ private static final String ATTR_PREPARED = "prepared";
private static final String ATTR_SEALED = "sealed";
private static final String ATTR_MODE = "mode";
private static final String ATTR_INSTALL_FLAGS = "installFlags";
@@ -148,7 +143,6 @@
private final Context mContext;
private final PackageManagerService mPm;
private final AppOpsManager mAppOps;
- private final StorageManager mStorage;
private final File mStagingDir;
private final HandlerThread mInstallThread;
@@ -190,7 +184,6 @@
mContext = context;
mPm = pm;
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- mStorage = StorageManager.from(mContext);
mStagingDir = stagingDir;
@@ -266,7 +259,9 @@
try {
final int sessionId = allocateSessionIdLocked();
mLegacySessions.put(sessionId, true);
- return prepareInternalStageDir(sessionId);
+ final File stageDir = buildInternalStageDir(sessionId);
+ prepareInternalStageDir(stageDir);
+ return stageDir;
} catch (IllegalStateException e) {
throw new IOException(e);
}
@@ -345,6 +340,7 @@
final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
+ final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
final SessionParams params = new SessionParams(
@@ -362,7 +358,7 @@
return new PackageInstallerSession(mInternalCallback, mContext, mPm,
mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
- createdMillis, stageDir, stageCid, sealed);
+ createdMillis, stageDir, stageCid, prepared, sealed);
}
private void writeSessionsLocked() {
@@ -410,6 +406,7 @@
if (session.stageCid != null) {
writeStringAttribute(out, ATTR_SESSION_STAGE_CID, session.stageCid);
}
+ writeBooleanAttribute(out, ATTR_PREPARED, session.isPrepared());
writeBooleanAttribute(out, ATTR_SEALED, session.isSealed());
writeIntAttribute(out, ATTR_MODE, params.mode);
@@ -483,14 +480,10 @@
}
}
- // TODO: treat INHERIT_EXISTING as install for user
-
- // Figure out where we're going to be staging session data
- final boolean stageInternal;
-
- if (params.mode == SessionParams.MODE_FULL_INSTALL) {
- // Brand new install, use best resolved location. This also verifies
- // that target has enough free space for the install.
+ if (params.mode == SessionParams.MODE_FULL_INSTALL
+ || params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+ // Resolve best location for install, based on combination of
+ // requested install flags, delta size, and manifest settings.
final long ident = Binder.clearCallingIdentity();
try {
final int resolved = PackageHelper.resolveInstallLocation(mContext,
@@ -498,46 +491,15 @@
params.installFlags);
if (resolved == PackageHelper.RECOMMEND_INSTALL_INTERNAL) {
- stageInternal = true;
+ params.setInstallFlagsInternal();
} else if (resolved == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
- stageInternal = false;
+ params.setInstallFlagsExternal();
} else {
throw new IOException("No storage with enough free space; res=" + resolved);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
- } else if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
- // Inheriting existing install, so stay on the same storage medium.
- final ApplicationInfo existingApp = mPm.getApplicationInfo(params.appPackageName, 0,
- userId);
- if (existingApp == null) {
- throw new IllegalStateException(
- "Missing existing app " + params.appPackageName);
- }
-
- final long existingSize;
- try {
- final PackageLite existingPkg = PackageParser.parsePackageLite(
- new File(existingApp.getCodePath()), 0);
- existingSize = PackageHelper.calculateInstalledSize(existingPkg, false,
- params.abiOverride);
- } catch (PackageParserException e) {
- throw new IllegalStateException(
- "Failed to calculate size of " + params.appPackageName);
- }
-
- if ((existingApp.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0) {
- // Internal we can link existing install into place, so we only
- // need enough space for the new data.
- checkInternalStorage(params.sizeBytes);
- stageInternal = true;
- } else {
- // External we're going to copy existing install into our
- // container, so we need footprint of both.
- checkExternalStorage(params.sizeBytes + existingSize);
- stageInternal = false;
- }
} else {
throw new IllegalArgumentException("Invalid install mode: " + params.mode);
}
@@ -563,15 +525,15 @@
// We're staging to exactly one location
File stageDir = null;
String stageCid = null;
- if (stageInternal) {
- stageDir = prepareInternalStageDir(sessionId);
+ if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+ stageDir = buildInternalStageDir(sessionId);
} else {
- stageCid = prepareExternalStageCid(sessionId, params.sizeBytes);
+ stageCid = buildExternalStageCid(sessionId);
}
session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
mInstallThread.getLooper(), sessionId, userId, installerPackageName, params,
- createdMillis, stageDir, stageCid, false);
+ createdMillis, stageDir, stageCid, false, false);
mSessions.put(sessionId, session);
}
@@ -581,6 +543,30 @@
}
@Override
+ public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {
+ synchronized (mSessions) {
+ final PackageInstallerSession session = mSessions.get(sessionId);
+ if (session == null || !isCallingUidOwner(session)) {
+ throw new SecurityException("Caller has no access to session " + sessionId);
+ }
+ session.params.appIcon = appIcon;
+ mInternalCallback.onSessionBadgingChanged(session);
+ }
+ }
+
+ @Override
+ public void updateSessionAppLabel(int sessionId, String appLabel) {
+ synchronized (mSessions) {
+ final PackageInstallerSession session = mSessions.get(sessionId);
+ if (session == null || !isCallingUidOwner(session)) {
+ throw new SecurityException("Caller has no access to session " + sessionId);
+ }
+ session.params.appLabel = appLabel;
+ mInternalCallback.onSessionBadgingChanged(session);
+ }
+ }
+
+ @Override
public void abandonSession(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
@@ -591,32 +577,16 @@
}
}
- private void checkInternalStorage(long sizeBytes) throws IOException {
- if (sizeBytes <= 0) return;
-
- final File target = Environment.getDataDirectory();
- final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
- mPm.freeStorage(targetBytes);
- if (target.getUsableSpace() < targetBytes) {
- throw new IOException("Not enough internal space to write " + sizeBytes + " bytes");
- }
- }
-
- private void checkExternalStorage(long sizeBytes) throws IOException {
- if (sizeBytes <= 0) return;
-
- final File target = new UserEnvironment(UserHandle.USER_OWNER)
- .getExternalStorageDirectory();
- final long targetBytes = sizeBytes + mStorage.getStorageLowBytes(target);
-
- if (target.getUsableSpace() < targetBytes) {
- throw new IOException("Not enough external space to write " + sizeBytes + " bytes");
- }
- }
-
@Override
public IPackageInstallerSession openSession(int sessionId) {
+ try {
+ return openSessionInternal(sessionId);
+ } catch (IOException e) {
+ throw ExceptionUtils.wrap(e);
+ }
+ }
+
+ private IPackageInstallerSession openSessionInternal(int sessionId) throws IOException {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
if (session == null || !isCallingUidOwner(session)) {
@@ -641,49 +611,43 @@
throw new IllegalStateException("Failed to allocate session ID");
}
- private File prepareInternalStageDir(int sessionId) throws IOException {
- final File file = new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+ private File buildInternalStageDir(int sessionId) {
+ return new File(mStagingDir, "vmdl" + sessionId + ".tmp");
+ }
- if (file.exists()) {
- throw new IOException("Session dir already exists: " + file);
+ static void prepareInternalStageDir(File stageDir) throws IOException {
+ if (stageDir.exists()) {
+ throw new IOException("Session dir already exists: " + stageDir);
}
try {
- Os.mkdir(file.getAbsolutePath(), 0755);
- Os.chmod(file.getAbsolutePath(), 0755);
+ Os.mkdir(stageDir.getAbsolutePath(), 0755);
+ Os.chmod(stageDir.getAbsolutePath(), 0755);
} catch (ErrnoException e) {
// This purposefully throws if directory already exists
- throw new IOException("Failed to prepare session dir", e);
+ throw new IOException("Failed to prepare session dir: " + stageDir, e);
}
- if (!SELinux.restorecon(file)) {
- throw new IOException("Failed to restorecon session dir");
+ if (!SELinux.restorecon(stageDir)) {
+ throw new IOException("Failed to restorecon session dir: " + stageDir);
}
-
- return file;
}
- private String prepareExternalStageCid(int sessionId, long sizeBytes) throws IOException {
- if (sizeBytes <= 0) {
- throw new IOException("Session must provide valid size for ASEC");
- }
+ private String buildExternalStageCid(int sessionId) {
+ return "smdl" + sessionId + ".tmp";
+ }
- final String cid = "smdl" + sessionId + ".tmp";
- if (PackageHelper.createSdDir(sizeBytes, cid, PackageManagerService.getEncryptKey(),
+ static void prepareExternalStageCid(String stageCid, long sizeBytes) throws IOException {
+ if (PackageHelper.createSdDir(sizeBytes, stageCid, PackageManagerService.getEncryptKey(),
Process.SYSTEM_UID, true) == null) {
- throw new IOException("Failed to create ASEC");
+ throw new IOException("Failed to create session cid: " + stageCid);
}
-
- return cid;
}
@Override
public SessionInfo getSessionInfo(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- if (!isCallingUidOwner(session)) {
- enforceCallerCanReadSessions();
- }
return session != null ? session.generateInfo() : null;
}
}
@@ -691,7 +655,6 @@
@Override
public List<SessionInfo> getAllSessions(int userId) {
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions");
- enforceCallerCanReadSessions();
final List<SessionInfo> result = new ArrayList<>();
synchronized (mSessions) {
@@ -755,8 +718,6 @@
@Override
public void registerCallback(IPackageInstallerCallback callback, int userId) {
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
- enforceCallerCanReadSessions();
-
mCallbacks.register(callback, userId);
}
@@ -787,21 +748,6 @@
}
}
- /**
- * We allow those with permission, or the current home app.
- */
- private void enforceCallerCanReadSessions() {
- final boolean hasPermission = (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.READ_INSTALL_SESSIONS)
- == PackageManager.PERMISSION_GRANTED);
- final boolean isHomeApp = mPm.checkCallerIsHomeApp();
- if (hasPermission || isHomeApp) {
- return;
- } else {
- throw new SecurityException("Caller must be current home app to read install sessions");
- }
- }
-
static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
private final Context mContext;
private final IntentSender mTarget;
@@ -893,9 +839,9 @@
private static class Callbacks extends Handler {
private static final int MSG_SESSION_CREATED = 1;
- private static final int MSG_SESSION_OPENED = 2;
- private static final int MSG_SESSION_PROGRESS_CHANGED = 3;
- private static final int MSG_SESSION_CLOSED = 4;
+ private static final int MSG_SESSION_BADGING_CHANGED = 2;
+ private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
private static final int MSG_SESSION_FINISHED = 5;
private final RemoteCallbackList<IPackageInstallerCallback>
@@ -938,15 +884,15 @@
case MSG_SESSION_CREATED:
callback.onSessionCreated(sessionId);
break;
- case MSG_SESSION_OPENED:
- callback.onSessionOpened(sessionId);
+ case MSG_SESSION_BADGING_CHANGED:
+ callback.onSessionBadgingChanged(sessionId);
+ break;
+ case MSG_SESSION_ACTIVE_CHANGED:
+ callback.onSessionActiveChanged(sessionId, (boolean) msg.obj);
break;
case MSG_SESSION_PROGRESS_CHANGED:
callback.onSessionProgressChanged(sessionId, (float) msg.obj);
break;
- case MSG_SESSION_CLOSED:
- callback.onSessionClosed(sessionId);
- break;
case MSG_SESSION_FINISHED:
callback.onSessionFinished(sessionId, (boolean) msg.obj);
break;
@@ -957,18 +903,18 @@
obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget();
}
- private void notifySessionOpened(int sessionId, int userId) {
- obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
+ private void notifySessionBadgingChanged(int sessionId, int userId) {
+ obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget();
+ }
+
+ private void notifySessionActiveChanged(int sessionId, int userId, boolean active) {
+ obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget();
}
private void notifySessionProgressChanged(int sessionId, int userId, float progress) {
obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget();
}
- private void notifySessionClosed(int sessionId, int userId) {
- obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget();
- }
-
public void notifySessionFinished(int sessionId, int userId, boolean success) {
obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget();
}
@@ -1006,18 +952,19 @@
}
class InternalCallback {
+ public void onSessionBadgingChanged(PackageInstallerSession session) {
+ mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
+ writeSessionsAsync();
+ }
+
+ public void onSessionActiveChanged(PackageInstallerSession session, boolean active) {
+ mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active);
+ }
+
public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
}
- public void onSessionOpened(PackageInstallerSession session) {
- mCallbacks.notifySessionOpened(session.sessionId, session.userId);
- }
-
- public void onSessionClosed(PackageInstallerSession session) {
- mCallbacks.notifySessionClosed(session.sessionId, session.userId);
- }
-
public void onSessionFinished(PackageInstallerSession session, boolean success) {
mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
synchronized (mSessions) {
@@ -1027,6 +974,12 @@
writeSessionsAsync();
}
+ public void onSessionPrepared(PackageInstallerSession session) {
+ // We prepared the destination to write into; we want to persist
+ // this, but it's not critical enough to block for.
+ writeSessionsAsync();
+ }
+
public void onSessionSealed(PackageInstallerSession session) {
// It's very important that we block until we've recorded the
// session as being sealed, since we never want to allow mutation
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5264fc4..06f550d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,15 +17,15 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
-import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
-import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
+import static com.android.server.pm.PackageInstallerService.prepareExternalStageCid;
+import static com.android.server.pm.PackageInstallerService.prepareInternalStageDir;
import android.content.Context;
import android.content.Intent;
@@ -88,8 +88,6 @@
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
- // TODO: treat INHERIT_EXISTING as installExistingPackage()
-
private final PackageInstallerService.InternalCallback mCallback;
private final Context mContext;
private final PackageManagerService mPm;
@@ -108,18 +106,23 @@
/** Note that UID is not persisted; it's always derived at runtime. */
final int installerUid;
- private final AtomicInteger mOpenCount = new AtomicInteger();
+ private final AtomicInteger mActiveCount = new AtomicInteger();
private final Object mLock = new Object();
@GuardedBy("mLock")
private float mClientProgress = 0;
@GuardedBy("mLock")
+ private float mInternalProgress = 0;
+
+ @GuardedBy("mLock")
private float mProgress = 0;
@GuardedBy("mLock")
private float mReportedProgress = -1;
@GuardedBy("mLock")
+ private boolean mPrepared = false;
+ @GuardedBy("mLock")
private boolean mSealed = false;
@GuardedBy("mLock")
private boolean mPermissionsAccepted = false;
@@ -184,7 +187,7 @@
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
String installerPackageName, SessionParams params, long createdMillis,
- File stageDir, String stageCid, boolean sealed) {
+ File stageDir, String stageCid, boolean prepared, boolean sealed) {
mCallback = callback;
mContext = context;
mPm = pm;
@@ -203,6 +206,7 @@
"Exactly one of stageDir or stageCid stage must be set");
}
+ mPrepared = prepared;
mSealed = sealed;
// Always derived at runtime
@@ -214,8 +218,6 @@
} else {
mPermissionsAccepted = false;
}
-
- computeProgressLocked();
}
public SessionInfo generateInfo() {
@@ -227,7 +229,7 @@
mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
- info.open = mOpenCount.get() > 0;
+ info.active = mActiveCount.get() > 0;
info.mode = params.mode;
info.sizeBytes = params.sizeBytes;
@@ -238,14 +240,23 @@
return info;
}
+ public boolean isPrepared() {
+ synchronized (mLock) {
+ return mPrepared;
+ }
+ }
+
public boolean isSealed() {
synchronized (mLock) {
return mSealed;
}
}
- private void assertNotSealed(String cookie) {
+ private void assertPreparedAndNotSealed(String cookie) {
synchronized (mLock) {
+ if (!mPrepared) {
+ throw new IllegalStateException(cookie + " before prepared");
+ }
if (mSealed) {
throw new SecurityException(cookie + " not allowed after commit");
}
@@ -278,28 +289,26 @@
@Override
public void setClientProgress(float progress) {
synchronized (mLock) {
+ // Always publish first staging movement
+ final boolean forcePublish = (mClientProgress == 0);
mClientProgress = progress;
- computeProgressLocked();
+ computeProgressLocked(forcePublish);
}
- maybePublishProgress();
}
@Override
public void addClientProgress(float progress) {
synchronized (mLock) {
- mClientProgress += progress;
- computeProgressLocked();
+ setClientProgress(mClientProgress + progress);
}
- maybePublishProgress();
}
- private void computeProgressLocked() {
- mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
- }
+ private void computeProgressLocked(boolean forcePublish) {
+ mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f)
+ + MathUtils.constrain(mInternalProgress * 0.2f, 0f, 0.2f);
- private void maybePublishProgress() {
// Only publish when meaningful change
- if (Math.abs(mProgress - mReportedProgress) > 0.01) {
+ if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) {
mReportedProgress = mProgress;
mCallback.onSessionProgressChanged(this, mProgress);
}
@@ -307,7 +316,7 @@
@Override
public String[] getNames() {
- assertNotSealed("getNames");
+ assertPreparedAndNotSealed("getNames");
try {
return resolveStageDir().list();
} catch (IOException e) {
@@ -331,7 +340,7 @@
// will block any attempted install transitions.
final FileBridge bridge;
synchronized (mLock) {
- assertNotSealed("openWrite");
+ assertPreparedAndNotSealed("openWrite");
bridge = new FileBridge();
mBridges.add(bridge);
@@ -385,7 +394,7 @@
}
private ParcelFileDescriptor openReadInternal(String name) throws IOException {
- assertNotSealed("openRead");
+ assertPreparedAndNotSealed("openRead");
try {
if (!FileUtils.isValidExtFilename(name)) {
@@ -405,6 +414,30 @@
public void commit(IntentSender statusReceiver) {
Preconditions.checkNotNull(statusReceiver);
+ synchronized (mLock) {
+ if (!mSealed) {
+ // Verify that all writers are hands-off
+ for (FileBridge bridge : mBridges) {
+ if (!bridge.isClosed()) {
+ throw new SecurityException("Files still open");
+ }
+ }
+
+ // Persist the fact that we've sealed ourselves to prevent
+ // mutations of any hard links we create.
+ mSealed = true;
+ mCallback.onSessionSealed(this);
+ }
+ }
+
+ // Client staging is fully done at this point
+ mClientProgress = 1f;
+ computeProgressLocked(true);
+
+ // This ongoing commit should keep session active, even though client
+ // will probably close their end.
+ mActiveCount.incrementAndGet();
+
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(mContext,
statusReceiver, sessionId);
mHandler.obtainMessage(MSG_COMMIT, adapter.getBinder()).sendToTarget();
@@ -412,22 +445,10 @@
private void commitLocked() throws PackageManagerException {
if (mDestroyed) {
- throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session");
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
}
-
- // Verify that all writers are hands-off
if (!mSealed) {
- for (FileBridge bridge : mBridges) {
- if (!bridge.isClosed()) {
- throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
- "Files still open");
- }
- }
- mSealed = true;
-
- // Persist the fact that we've sealed ourselves to prevent mutations
- // of any hard links we create below.
- mCallback.onSessionSealed(this);
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
}
try {
@@ -456,6 +477,10 @@
mRemoteObserver.onUserActionRequired(intent);
} catch (RemoteException ignored) {
}
+
+ // Commit was keeping session marked as active until now; release
+ // that extra refcount so session appears idle.
+ close();
return;
}
@@ -485,7 +510,8 @@
}
// TODO: surface more granular state from dexopt
- mCallback.onSessionProgressChanged(this, 0.9f);
+ mInternalProgress = 0.5f;
+ computeProgressLocked(true);
// Unpack native libraries
extractNativeLibraries(mResolvedStageDir, params.abiOverride);
@@ -553,8 +579,7 @@
try {
apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse " + file + ": " + e);
+ throw PackageManagerException.from(e);
}
if (!stagedSplits.add(apk.splitName)) {
@@ -620,8 +645,7 @@
existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()),
PackageParser.PARSE_COLLECT_CERTIFICATES);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse existing package " + app.getCodePath() + ": " + e);
+ throw PackageManagerException.from(e);
}
assertApkConsistent("Existing base", existingBase);
@@ -673,8 +697,7 @@
try {
baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
} catch (PackageParserException e) {
- throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
- "Failed to parse base package " + mResolvedBaseFile + ": " + e);
+ throw PackageManagerException.from(e);
}
final List<String> splitPaths = new ArrayList<>();
@@ -828,16 +851,36 @@
}
}
- public void open() {
- if (mOpenCount.getAndIncrement() == 0) {
- mCallback.onSessionOpened(this);
+ public void open() throws IOException {
+ if (mActiveCount.getAndIncrement() == 0) {
+ mCallback.onSessionActiveChanged(this, true);
+ }
+
+ synchronized (mLock) {
+ if (!mPrepared) {
+ if (stageDir != null) {
+ prepareInternalStageDir(stageDir);
+ } else if (stageCid != null) {
+ prepareExternalStageCid(stageCid, params.sizeBytes);
+
+ // TODO: deliver more granular progress for ASEC allocation
+ mInternalProgress = 0.25f;
+ computeProgressLocked(true);
+ } else {
+ throw new IllegalArgumentException(
+ "Exactly one of stageDir or stageCid stage must be set");
+ }
+
+ mPrepared = true;
+ mCallback.onSessionPrepared(this);
+ }
}
}
@Override
public void close() {
- if (mOpenCount.decrementAndGet() == 0) {
- mCallback.onSessionClosed(this);
+ if (mActiveCount.decrementAndGet() == 0) {
+ mCallback.onSessionActiveChanged(this, false);
}
}
@@ -866,6 +909,11 @@
synchronized (mLock) {
mSealed = true;
mDestroyed = true;
+
+ // Force shut down all bridges
+ for (FileBridge bridge : mBridges) {
+ bridge.forceClose();
+ }
}
if (stageDir != null) {
FileUtils.deleteContents(stageDir);
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index 0cbdcdc..a41636e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import android.content.pm.PackageParser.PackageParserException;
+
/** {@hide} */
public class PackageManagerException extends Exception {
public final int error;
@@ -29,4 +31,9 @@
super(detailMessage, throwable);
this.error = error;
}
+
+ public static PackageManagerException from(PackageParserException e)
+ throws PackageManagerException {
+ throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5639234..d821fc1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -312,6 +312,12 @@
final PackageHandler mHandler;
+ /**
+ * Messages for {@link #mHandler} that need to wait for system ready before
+ * being dispatched.
+ */
+ private ArrayList<Message> mPostSystemReadyMessages;
+
final int mSdkVersion = Build.VERSION.SDK_INT;
final Context mContext;
@@ -446,9 +452,9 @@
/** Token for keys in mPendingVerification. */
private int mPendingVerificationToken = 0;
- boolean mSystemReady;
- boolean mSafeMode;
- boolean mHasSystemUidErrors;
+ volatile boolean mSystemReady;
+ volatile boolean mSafeMode;
+ volatile boolean mHasSystemUidErrors;
ApplicationInfo mAndroidApplication;
final ActivityInfo mResolveActivity = new ActivityInfo();
@@ -3234,32 +3240,31 @@
// reader
synchronized (mPackages) {
final String pkgName = intent.getPackage();
- boolean queryCrossProfile = (flags & PackageManager.NO_CROSS_PROFILE) == 0;
if (pkgName == null) {
ResolveInfo resolveInfo = null;
- if (queryCrossProfile) {
- // Check if the intent needs to be forwarded to another user for this package
- ArrayList<ResolveInfo> crossProfileResult =
- queryIntentActivitiesCrossProfilePackage(
- intent, resolvedType, flags, userId);
- if (!crossProfileResult.isEmpty()) {
- // Skip the current profile
- return crossProfileResult;
- }
- List<CrossProfileIntentFilter> matchingFilters =
- getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
- // Check for results that need to skip the current profile.
- resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
- resolvedType, flags, userId);
- if (resolveInfo != null) {
- List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
- result.add(resolveInfo);
- return result;
- }
- // Check for cross profile results.
- resolveInfo = queryCrossProfileIntents(
- matchingFilters, intent, resolvedType, flags, userId);
+
+ // Check if the intent needs to be forwarded to another user for this package
+ ArrayList<ResolveInfo> crossProfileResult =
+ queryIntentActivitiesCrossProfilePackage(
+ intent, resolvedType, flags, userId);
+ if (!crossProfileResult.isEmpty()) {
+ // Skip the current profile
+ return crossProfileResult;
}
+ List<CrossProfileIntentFilter> matchingFilters =
+ getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
+ // Check for results that need to skip the current profile.
+ resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
+ resolvedType, flags, userId);
+ if (resolveInfo != null) {
+ List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
+ result.add(resolveInfo);
+ return result;
+ }
+ // Check for cross profile results.
+ resolveInfo = queryCrossProfileIntents(
+ matchingFilters, intent, resolvedType, flags, userId);
+
// Check for results in the current profile.
List<ResolveInfo> result = mActivities.queryIntent(
intent, resolvedType, flags, userId);
@@ -3271,14 +3276,12 @@
}
final PackageParser.Package pkg = mPackages.get(pkgName);
if (pkg != null) {
- if (queryCrossProfile) {
- ArrayList<ResolveInfo> crossProfileResult =
- queryIntentActivitiesCrossProfilePackage(
- intent, resolvedType, flags, userId, pkg, pkgName);
- if (!crossProfileResult.isEmpty()) {
- // Skip the current profile
- return crossProfileResult;
- }
+ ArrayList<ResolveInfo> crossProfileResult =
+ queryIntentActivitiesCrossProfilePackage(
+ intent, resolvedType, flags, userId, pkg, pkgName);
+ if (!crossProfileResult.isEmpty()) {
+ // Skip the current profile
+ return crossProfileResult;
}
return mActivities.queryIntentForPackage(intent, resolvedType, flags,
pkg.activities, userId);
@@ -3777,21 +3780,25 @@
} else {
pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
}
- if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
- if (numMatch == permissions.length) {
- pi.requestedPermissions = permissions;
- } else {
- pi.requestedPermissions = new String[numMatch];
- numMatch = 0;
- for (int i=0; i<permissions.length; i++) {
- if (tmp[i]) {
- pi.requestedPermissions[numMatch] = permissions[i];
- numMatch++;
+ // The above might return null in cases of uninstalled apps or install-state
+ // skew across users/profiles.
+ if (pi != null) {
+ if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+ if (numMatch == permissions.length) {
+ pi.requestedPermissions = permissions;
+ } else {
+ pi.requestedPermissions = new String[numMatch];
+ numMatch = 0;
+ for (int i=0; i<permissions.length; i++) {
+ if (tmp[i]) {
+ pi.requestedPermissions[numMatch] = permissions[i];
+ numMatch++;
+ }
}
}
}
+ list.add(pi);
}
- list.add(pi);
}
@Override
@@ -4155,8 +4162,7 @@
pp.collectCertificates(pkg, parseFlags);
pp.collectManifestDigest(pkg);
} catch (PackageParserException e) {
- throw new PackageManagerException(e.error, "Failed to collect certificates for "
- + pkg.packageName + ": " + e.getMessage());
+ throw PackageManagerException.from(e);
}
}
@@ -4181,8 +4187,7 @@
try {
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
- throw new PackageManagerException(e.error,
- "Failed to scan " + scanFile + ": " + e.getMessage());
+ throw PackageManagerException.from(e);
}
PackageSetting ps = null;
@@ -4512,7 +4517,7 @@
@Override
public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
- return performDexOpt(packageName, instructionSet, true);
+ return performDexOpt(packageName, instructionSet, false);
}
private static String getPrimaryInstructionSet(ApplicationInfo info) {
@@ -4523,8 +4528,11 @@
return VMRuntime.getInstructionSet(info.primaryCpuAbi);
}
- public boolean performDexOpt(String packageName, String instructionSet, boolean updateUsage) {
- if (!mLazyDexOpt) {
+ public boolean performDexOpt(String packageName, String instructionSet, boolean backgroundDexopt) {
+ boolean dexopt = mLazyDexOpt || backgroundDexopt;
+ boolean updateUsage = !backgroundDexopt; // Don't update usage if this is just a backgroundDexopt
+ if (!dexopt && !updateUsage) {
+ // We aren't going to dexopt or update usage, so bail early.
return false;
}
PackageParser.Package p;
@@ -4538,6 +4546,10 @@
p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
}
mPackageUsage.write(false);
+ if (!dexopt) {
+ // We aren't going to dexopt, so bail early.
+ return false;
+ }
targetInstructionSet = instructionSet != null ? instructionSet :
getPrimaryInstructionSet(p.applicationInfo);
@@ -7678,16 +7690,18 @@
}
void schedulePackageCleaning(String packageName, int userId, boolean andCode) {
- if (false) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.d(TAG, "Schedule cleaning " + packageName + " user=" + userId
- + " andCode=" + andCode, here);
+ final Message msg = mHandler.obtainMessage(START_CLEANING_PACKAGE,
+ userId, andCode ? 1 : 0, packageName);
+ if (mSystemReady) {
+ msg.sendToTarget();
+ } else {
+ if (mPostSystemReadyMessages == null) {
+ mPostSystemReadyMessages = new ArrayList<>();
+ }
+ mPostSystemReadyMessages.add(msg);
}
- mHandler.sendMessage(mHandler.obtainMessage(START_CLEANING_PACKAGE,
- userId, andCode ? 1 : 0, packageName));
}
-
+
void startCleaningPackages() {
// reader
synchronized (mPackages) {
@@ -10238,8 +10252,18 @@
if (bp != null) {
// If the defining package is signed with our cert, it's okay. This
// also includes the "updating the same package" case, of course.
- if (compareSignatures(bp.packageSetting.signatures.mSignatures,
- pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+ // "updating same package" could also involve key-rotation.
+ final boolean sigsOk;
+ if (!bp.sourcePackage.equals(pkg.packageName)
+ || !(bp.packageSetting instanceof PackageSetting)
+ || !bp.packageSetting.keySetData.isUsingUpgradeKeySets()
+ || ((PackageSetting) bp.packageSetting).sharedUser != null) {
+ sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
+ pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
+ } else {
+ sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
+ }
+ if (!sigsOk) {
// If the owning package is the system itself, we log but allow
// install to proceed; we fail the install on all other permission
// redefinitions.
@@ -11721,47 +11745,6 @@
preferred.activityInfo.name);
}
- /**
- * Check if calling UID is the current home app. This handles both the case
- * where the user has selected a specific home app, and where there is only
- * one home app.
- */
- public boolean checkCallerIsHomeApp() {
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
-
- final int callingUid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getCallingUserId();
- final List<ResolveInfo> allHomes = queryIntentActivities(intent, null, 0, callingUserId);
- final ResolveInfo preferredHome = findPreferredActivity(intent, null, 0, allHomes, 0, true,
- false, false, callingUserId);
-
- if (preferredHome != null) {
- if (callingUid == preferredHome.activityInfo.applicationInfo.uid) {
- return true;
- }
- } else {
- for (ResolveInfo info : allHomes) {
- if (callingUid == info.activityInfo.applicationInfo.uid) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Enforce that calling UID is the current home app. This handles both the
- * case where the user has selected a specific home app, and where there is
- * only one home app.
- */
- public void enforceCallerIsHomeApp() {
- if (!checkCallerIsHomeApp()) {
- throw new SecurityException("Caller is not currently selected home app");
- }
- }
-
@Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
@@ -12021,6 +12004,14 @@
}
}
sUserManager.systemReady();
+
+ // Kick off any messages waiting for system ready
+ if (mPostSystemReadyMessages != null) {
+ for (Message msg : mPostSystemReadyMessages) {
+ msg.sendToTarget();
+ }
+ mPostSystemReadyMessages = null;
+ }
}
@Override
@@ -13018,6 +13009,9 @@
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
+ if (ps.pkg == null) {
+ continue;
+ }
final String packageName = ps.pkg.packageName;
// Skip over if system app
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c346f71..c1caeac 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -602,11 +602,8 @@
// original default value is true), or we are being
// asked to install for all users, or this is the
// user we are installing for.
- // In this context all users (USER_ALL) implies an adb install,
- // so we additionally check whether that is allowed for this user.
final boolean installed = installUser == null
- || (installUser.getIdentifier() == UserHandle.USER_ALL
- && (!isUnknownSourcesDisallowed(user.id)))
+ || installUser.getIdentifier() == UserHandle.USER_ALL
|| installUser.getIdentifier() == user.id;
p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
@@ -673,10 +670,7 @@
List<UserInfo> users = getAllUsers();
if (users != null) {
for (UserInfo user : users) {
- // Installing for USER_ALL implies an adb install, so we
- // additionally check whether that is allowed for this user.
- if ((installUser.getIdentifier() == UserHandle.USER_ALL
- && (!isUnknownSourcesDisallowed(user.id)))
+ if (installUser.getIdentifier() == UserHandle.USER_ALL
|| installUser.getIdentifier() == user.id) {
boolean installed = p.getInstalled(user.id);
if (!installed) {
@@ -691,12 +685,6 @@
return p;
}
- boolean isUnknownSourcesDisallowed(int userId) {
- UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- return um.getUserRestrictions(new UserHandle(userId)).getBoolean(
- UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
- }
-
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
p.pkg = pkg;
// pkg.mSetEnabled = p.getEnabled(userId);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 4a2cece..d032d29 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -21,7 +21,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -92,6 +91,7 @@
private static final String ATTR_SERIAL_NO = "serialNumber";
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
+ private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
private static final String ATTR_USER_VERSION = "version";
private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions";
@@ -228,7 +228,7 @@
ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
for (int i = 0; i < mUsers.size(); i++) {
UserInfo ui = mUsers.valueAt(i);
- if (ui.partial && i != 0) {
+ if ((ui.partial || ui.guestToRemove) && i != 0) {
partials.add(ui);
}
}
@@ -759,6 +759,9 @@
if (userInfo.partial) {
serializer.attribute(null, ATTR_PARTIAL, "true");
}
+ if (userInfo.guestToRemove) {
+ serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
+ }
if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
Integer.toString(userInfo.profileGroupId));
@@ -806,7 +809,7 @@
serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber));
serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion));
- serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
+ serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
writeRestrictionsLocked(serializer, mGuestRestrictions);
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
for (int i = 0; i < mUsers.size(); i++) {
@@ -855,6 +858,8 @@
writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS);
writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
+ writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
serializer.endTag(null, TAG_RESTRICTIONS);
}
@@ -871,6 +876,7 @@
int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
long lastAttemptTime = 0L;
boolean partial = false;
+ boolean guestToRemove = false;
Bundle restrictions = new Bundle();
FileInputStream fis = null;
@@ -918,6 +924,10 @@
if ("true".equals(valueString)) {
partial = true;
}
+ valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
+ if ("true".equals(valueString)) {
+ guestToRemove = true;
+ }
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -942,6 +952,7 @@
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.partial = partial;
+ userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
mUserRestrictions.append(id, restrictions);
if (salt != 0L) {
@@ -999,6 +1010,8 @@
readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS);
readBoolean(parser, restrictions, UserManager.DISALLOW_SMS);
readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
+ readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM);
}
private void readBoolean(XmlPullParser parser, Bundle restrictions,
@@ -1119,7 +1132,7 @@
return null;
}
// If we're adding a guest and there already exists one, bail.
- if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) {
+ if (isGuest && findCurrentGuestUserLocked() != null) {
return null;
}
// Limit number of managed profiles that can be created
@@ -1180,6 +1193,23 @@
}
/**
+ * Find the current guest user. If the Guest user is partial,
+ * then do not include it in the results as it is about to die.
+ * This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to
+ * the special handling of Guests being removed.
+ */
+ private UserInfo findCurrentGuestUserLocked() {
+ final int size = mUsers.size();
+ for (int i = 0; i < size; i++) {
+ final UserInfo user = mUsers.valueAt(i);
+ if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) {
+ return user;
+ }
+ }
+ return null;
+ }
+
+ /**
* Mark this guest user for deletion to allow us to create another guest
* and switch to that user before actually removing this guest.
* @param userHandle the userid of the current guest
@@ -1204,14 +1234,15 @@
if (!user.isGuest()) {
return false;
}
- // Set this to a partially created user, so that the user will be purged
- // on next startup, in case the runtime stops now before stopping and
- // removing the user completely.
- user.partial = true;
+ // We set this to a guest user that is to be removed. This is a temporary state
+ // where we are allowed to add new Guest users, even if this one is still not
+ // removed. This user will still show up in getUserInfo() calls.
+ // If we don't get around to removing this Guest user, it will be purged on next
+ // startup.
+ user.guestToRemove = true;
// Mark it as disabled, so that it isn't returned any more when
// profiles are queried.
user.flags |= UserInfo.FLAG_DISABLED;
- user.flags &= ~UserInfo.FLAG_GUEST;
writeUserLocked(user);
}
} finally {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3eb2d5f..e1ade63 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -42,6 +42,7 @@
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -85,6 +86,7 @@
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
+import com.android.internal.R;
public class WallpaperManagerService extends IWallpaperManager.Stub {
static final String TAG = "WallpaperManagerService";
@@ -99,12 +101,6 @@
static final long MIN_WALLPAPER_CRASH_TIME = 10000;
static final String WALLPAPER = "wallpaper";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
- /**
- * Name of the component used to display bitmap wallpapers from either the gallery or
- * built-in wallpapers.
- */
- static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
- "com.android.systemui.ImageWallpaper");
/**
* Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
@@ -146,7 +142,7 @@
if (event == CLOSE_WRITE) {
mWallpaper.imageWallpaperPending = false;
}
- bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
+ bindWallpaperComponentLocked(mImageWallpaper, true,
false, mWallpaper, null);
saveSettingsLocked(mWallpaper);
}
@@ -161,6 +157,12 @@
final MyPackageMonitor mMonitor;
WallpaperData mLastWallpaper;
+ /**
+ * Name of the component used to display bitmap wallpapers from either the gallery or
+ * built-in wallpapers.
+ */
+ final ComponentName mImageWallpaper;
+
SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
int mCurrentUserId;
@@ -205,6 +207,8 @@
int width = -1;
int height = -1;
+ final Rect padding = new Rect(0, 0, 0, 0);
+
WallpaperData(int userId) {
this.userId = userId;
wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
@@ -221,6 +225,7 @@
IRemoteCallback mReply;
boolean mDimensionsChanged = false;
+ boolean mPaddingChanged = false;
public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
mInfo = info;
@@ -282,6 +287,14 @@
}
mDimensionsChanged = false;
}
+ if (mPaddingChanged) {
+ try {
+ mEngine.setDisplayPadding(mWallpaper.padding);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to set wallpaper padding", e);
+ }
+ mPaddingChanged = false;
+ }
}
}
@@ -447,6 +460,8 @@
public WallpaperManagerService(Context context) {
if (DEBUG) Slog.v(TAG, "WallpaperService startup");
mContext = context;
+ mImageWallpaper = ComponentName.unflattenFromString(
+ context.getResources().getString(R.string.image_wallpaper_component));
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
mIPackageManager = AppGlobals.getPackageManager();
@@ -599,33 +614,35 @@
f.delete();
}
final long ident = Binder.clearCallingIdentity();
- RuntimeException e = null;
try {
- wallpaper.imageWallpaperPending = false;
- if (userId != mCurrentUserId) return;
- if (bindWallpaperComponentLocked(defaultFailed
- ? IMAGE_WALLPAPER
- : null, true, false, wallpaper, reply)) {
- return;
+ RuntimeException e = null;
+ try {
+ wallpaper.imageWallpaperPending = false;
+ if (userId != mCurrentUserId) return;
+ if (bindWallpaperComponentLocked(defaultFailed
+ ? mImageWallpaper
+ : null, true, false, wallpaper, reply)) {
+ return;
+ }
+ } catch (IllegalArgumentException e1) {
+ e = e1;
}
- } catch (IllegalArgumentException e1) {
- e = e1;
+
+ // This can happen if the default wallpaper component doesn't
+ // exist. This should be a system configuration problem, but
+ // let's not let it crash the system and just live with no
+ // wallpaper.
+ Slog.e(TAG, "Default wallpaper component not found!", e);
+ clearWallpaperComponentLocked(wallpaper);
+ if (reply != null) {
+ try {
+ reply.sendResult(null);
+ } catch (RemoteException e1) {
+ }
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
-
- // This can happen if the default wallpaper component doesn't
- // exist. This should be a system configuration problem, but
- // let's not let it crash the system and just live with no
- // wallpaper.
- Slog.e(TAG, "Default wallpaper component not found!", e);
- clearWallpaperComponentLocked(wallpaper);
- if (reply != null) {
- try {
- reply.sendResult(null);
- } catch (RemoteException e1) {
- }
- }
}
public boolean hasNamedWallpaper(String name) {
@@ -714,6 +731,40 @@
}
}
+ public void setDisplayPadding(Rect padding) {
+ checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
+ synchronized (mLock) {
+ int userId = UserHandle.getCallingUserId();
+ WallpaperData wallpaper = mWallpaperMap.get(userId);
+ if (wallpaper == null) {
+ throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
+ }
+ if (padding.left < 0 || padding.top < 0 || padding.right < 0 || padding.bottom < 0) {
+ throw new IllegalArgumentException("padding must be positive: " + padding);
+ }
+
+ if (!padding.equals(wallpaper.padding)) {
+ wallpaper.padding.set(padding);
+ saveSettingsLocked(wallpaper);
+ if (mCurrentUserId != userId) return; // Don't change the properties now
+ if (wallpaper.connection != null) {
+ if (wallpaper.connection.mEngine != null) {
+ try {
+ wallpaper.connection.mEngine.setDisplayPadding(padding);
+ } catch (RemoteException e) {
+ }
+ notifyCallbacksLocked(wallpaper);
+ } else if (wallpaper.connection.mService != null) {
+ // We've attached to the service but the engine hasn't attached back to us
+ // yet. This means it will be created with the previous dimensions, so we
+ // need to update it to the new dimensions once it attaches.
+ wallpaper.connection.mPaddingChanged = true;
+ }
+ }
+ }
+ }
+ }
+
public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
Bundle outParams) {
synchronized (mLock) {
@@ -848,7 +899,7 @@
componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
if (componentName == null) {
// Fall back to static image wallpaper
- componentName = IMAGE_WALLPAPER;
+ componentName = mImageWallpaper;
//clearWallpaperComponentLocked();
//return;
if (DEBUG) Slog.v(TAG, "Using image wallpaper");
@@ -876,7 +927,7 @@
WallpaperInfo wi = null;
Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
- if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
+ if (componentName != null && !componentName.equals(mImageWallpaper)) {
// Make sure the selected service is actually a wallpaper service.
List<ResolveInfo> ris =
mIPackageManager.queryIntentServices(intent,
@@ -1001,7 +1052,7 @@
try {
conn.mService.attach(conn, conn.mToken,
WindowManager.LayoutParams.TYPE_WALLPAPER, false,
- wallpaper.width, wallpaper.height);
+ wallpaper.width, wallpaper.height, wallpaper.padding);
} catch (RemoteException e) {
Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
if (!wallpaper.wallpaperUpdating) {
@@ -1050,9 +1101,21 @@
out.startTag(null, "wp");
out.attribute(null, "width", Integer.toString(wallpaper.width));
out.attribute(null, "height", Integer.toString(wallpaper.height));
+ if (wallpaper.padding.left != 0) {
+ out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
+ }
+ if (wallpaper.padding.top != 0) {
+ out.attribute(null, "paddingTop", Integer.toString(wallpaper.padding.top));
+ }
+ if (wallpaper.padding.right != 0) {
+ out.attribute(null, "paddingRight", Integer.toString(wallpaper.padding.right));
+ }
+ if (wallpaper.padding.bottom != 0) {
+ out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
+ }
out.attribute(null, "name", wallpaper.name);
if (wallpaper.wallpaperComponent != null
- && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
+ && !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
out.attribute(null, "component",
wallpaper.wallpaperComponent.flattenToShortString());
}
@@ -1086,6 +1149,14 @@
}
}
+ private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
+ String value = parser.getAttributeValue(null, name);
+ if (value == null) {
+ return defValue;
+ }
+ return Integer.parseInt(value);
+ }
+
private void loadSettingsLocked(int userId) {
if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
@@ -1116,6 +1187,10 @@
wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
wallpaper.height = Integer.parseInt(parser
.getAttributeValue(null, "height"));
+ wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
+ wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
+ wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
+ wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0);
wallpaper.name = parser.getAttributeValue(null, "name");
String comp = parser.getAttributeValue(null, "component");
wallpaper.nextWallpaperComponent = comp != null
@@ -1124,7 +1199,7 @@
if (wallpaper.nextWallpaperComponent == null
|| "android".equals(wallpaper.nextWallpaperComponent
.getPackageName())) {
- wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
+ wallpaper.nextWallpaperComponent = mImageWallpaper;
}
if (DEBUG) {
@@ -1162,6 +1237,7 @@
if (!success) {
wallpaper.width = -1;
wallpaper.height = -1;
+ wallpaper.padding.set(0, 0, 0, 0);
wallpaper.name = "";
}
@@ -1196,7 +1272,7 @@
loadSettingsLocked(0);
wallpaper = mWallpaperMap.get(0);
if (wallpaper.nextWallpaperComponent != null
- && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
+ && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) {
if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
wallpaper, null)) {
// No such live wallpaper or other failure; fall back to the default
@@ -1325,13 +1401,12 @@
WallpaperData wallpaper = mWallpaperMap.valueAt(i);
pw.println(" User " + wallpaper.userId + ":");
pw.print(" mWidth=");
- pw.print(wallpaper.width);
- pw.print(" mHeight=");
- pw.println(wallpaper.height);
- pw.print(" mName=");
- pw.println(wallpaper.name);
- pw.print(" mWallpaperComponent=");
- pw.println(wallpaper.wallpaperComponent);
+ pw.print(wallpaper.width);
+ pw.print(" mHeight=");
+ pw.println(wallpaper.height);
+ pw.print(" mPadding="); pw.println(wallpaper.padding);
+ pw.print(" mName="); pw.println(wallpaper.name);
+ pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
if (wallpaper.connection != null) {
WallpaperConnection conn = wallpaper.connection;
pw.print(" Wallpaper connection ");
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index aabb8f7..bfc7659 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -569,9 +569,9 @@
int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
Rect contentInsets, boolean isFullScreen) {
Animation a;
- final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ final int thumbWidthI = mNextAppTransitionStartWidth;
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
- final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final int thumbHeightI = mNextAppTransitionStartHeight;
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
// Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
@@ -993,7 +993,7 @@
}
void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
- IRemoteCallback startedCallback, boolean scaleUp) {
+ int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
if (isTransitionSet()) {
mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
: NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
@@ -1002,6 +1002,8 @@
mNextAppTransitionScaleUp = scaleUp;
mNextAppTransitionStartX = startX;
mNextAppTransitionStartY = startY;
+ mNextAppTransitionStartWidth = targetWidth;
+ mNextAppTransitionStartHeight = targetHeight;
postAnimationCallback();
mNextAppTransitionCallback = startedCallback;
} else {
@@ -1138,6 +1140,10 @@
pw.print(mNextAppTransitionStartX);
pw.print(" mNextAppTransitionStartY=");
pw.println(mNextAppTransitionStartY);
+ pw.print(" mNextAppTransitionStartWidth=");
+ pw.print(mNextAppTransitionStartWidth);
+ pw.print(" mNextAppTransitionStartHeight=");
+ pw.println(mNextAppTransitionStartHeight);
pw.print(" mNextAppTransitionScaleUp="); pw.println(mNextAppTransitionScaleUp);
break;
}
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index 64b852b..a7d41fa 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -63,8 +63,14 @@
SurfaceControl ctrl = null;
try {
- ctrl = new SurfaceControl(session, "CircularDisplayMask",
- mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowStateAnimator.SurfaceTrace(session, "CircularDisplayMask",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
new file mode 100644
index 0000000..62f2b48
--- /dev/null
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2014 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.wm;
+
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class EmulatorDisplayOverlay {
+ private static final String TAG = "EmulatorDisplayOverlay";
+
+ // Display dimensions
+ private Point mScreenSize;
+
+ private final SurfaceControl mSurfaceControl;
+ private final Surface mSurface = new Surface();
+ private int mLastDW;
+ private int mLastDH;
+ private boolean mDrawNeeded;
+ private Drawable mOverlay;
+ private int mRotation;
+ private boolean mVisible;
+
+ public EmulatorDisplayOverlay(Context context, Display display, SurfaceSession session,
+ int zOrder) {
+ mScreenSize = new Point();
+ display.getSize(mScreenSize);
+
+ SurfaceControl ctrl = null;
+ try {
+ if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+ ctrl = new WindowStateAnimator.SurfaceTrace(session, "EmulatorDisplayOverlay",
+ mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT,
+ SurfaceControl.HIDDEN);
+ } else {
+ ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x,
+ mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ }
+ ctrl.setLayerStack(display.getLayerStack());
+ ctrl.setLayer(zOrder);
+ ctrl.setPosition(0, 0);
+ ctrl.show();
+ mSurface.copyFrom(ctrl);
+ } catch (OutOfResourcesException e) {
+ }
+ mSurfaceControl = ctrl;
+ mDrawNeeded = true;
+ mOverlay = context.getDrawable(
+ com.android.internal.R.drawable.emulator_circular_window_overlay);
+ }
+
+ private void drawIfNeeded() {
+ if (!mDrawNeeded || !mVisible) {
+ return;
+ }
+ mDrawNeeded = false;
+
+ Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ } catch (OutOfResourcesException e) {
+ }
+ if (c == null) {
+ return;
+ }
+ c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
+ mSurfaceControl.setPosition(0, 0);
+ mOverlay.setBounds(0, 0, mScreenSize.x, mScreenSize.y);
+ mOverlay.draw(c);
+ mSurface.unlockCanvasAndPost(c);
+ }
+
+ // Note: caller responsible for being inside
+ // Surface.openTransaction() / closeTransaction()
+ public void setVisibility(boolean on) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ mVisible = on;
+ drawIfNeeded();
+ if (on) {
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+ }
+
+ void positionSurface(int dw, int dh, int rotation) {
+ if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
+ return;
+ }
+ mLastDW = dw;
+ mLastDH = dh;
+ mDrawNeeded = true;
+ mRotation = rotation;
+ drawIfNeeded();
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f02c0e6..46aefb6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -352,6 +352,12 @@
mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
}
+ /* Notifies that the camera lens cover state has changed. */
+ @Override
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+ mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+ }
+
/* Provides an opportunity for the window manager policy to intercept early key
* processing as soon as the key has been read from the device. */
@Override
@@ -359,12 +365,13 @@
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
- /* Provides an opportunity for the window manager policy to intercept early
- * motion event processing when the screen is off since these events are normally
+ /* Provides an opportunity for the window manager policy to intercept early motion event
+ * processing when the device is in a non-interactive state since these events are normally
* dropped. */
@Override
- public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
- return mService.mPolicy.interceptWakeMotionBeforeQueueing(whenNanos, policyFlags);
+ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
+ whenNanos, policyFlags);
}
/* Provides an opportunity for the window manager policy to process a key before
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index f2703ad..d737e7f 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -415,6 +415,18 @@
mService.wallpaperOffsetsComplete(window);
}
+ public void setWallpaperDisplayOffset(IBinder window, int x, int y) {
+ synchronized(mService.mWindowMap) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mService.setWindowWallpaperDisplayOffsetLocked(
+ mService.windowForClientLocked(this, window, true), x, y);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
int z, Bundle extras, boolean sync) {
synchronized(mService.mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 08343d8..10ab6b5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -20,6 +20,7 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import android.app.AppOpsManager;
+import android.os.Build;
import android.util.ArraySet;
import android.util.TimeUtils;
import android.view.IWindowId;
@@ -295,6 +296,8 @@
private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -441,6 +444,7 @@
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
CircularDisplayMask mCircularDisplayMask;
+ EmulatorDisplayOverlay mEmulatorDisplayOverlay;
FocusedStackFrame mFocusedStackFrame;
int mFocusedStackLayer;
@@ -572,6 +576,8 @@
float mLastWallpaperY = -1;
float mLastWallpaperXStep = -1;
float mLastWallpaperYStep = -1;
+ int mLastWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+ int mLastWallpaperDisplayOffsetY = Integer.MIN_VALUE;
// This is set when we are waiting for a wallpaper to tell us it is done
// changing its scroll position.
WindowState mWaitingOnWallpaper;
@@ -879,6 +885,7 @@
}
showCircularDisplayMaskIfNeeded();
+ showEmulatorDisplayOverlayIfNeeded();
}
public InputMonitor getInputMonitor() {
@@ -1892,6 +1899,12 @@
mLastWallpaperY = mWallpaperTarget.mWallpaperY;
mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
}
+ if (mWallpaperTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = mWallpaperTarget.mWallpaperDisplayOffsetX;
+ }
+ if (mWallpaperTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = mWallpaperTarget.mWallpaperDisplayOffsetY;
+ }
}
// Start stepping backwards from here, ensuring that our wallpaper windows
@@ -2030,6 +2043,9 @@
float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetX;
+ }
changed = wallpaperWin.mXOffset != offset;
if (changed) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
@@ -2046,6 +2062,9 @@
float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
+ if (mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ offset += mLastWallpaperDisplayOffsetY;
+ }
if (wallpaperWin.mYOffset != offset) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
+ wallpaperWin + " y: " + offset);
@@ -2130,6 +2149,16 @@
} else if (changingTarget.mWallpaperY >= 0) {
mLastWallpaperY = changingTarget.mWallpaperY;
}
+ if (target.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = target.mWallpaperDisplayOffsetX;
+ } else if (changingTarget.mWallpaperDisplayOffsetX != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetX = changingTarget.mWallpaperDisplayOffsetX;
+ }
+ if (target.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = target.mWallpaperDisplayOffsetY;
+ } else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
+ }
}
int curTokenIndex = mWallpaperTokens.size();
@@ -2826,6 +2855,14 @@
}
}
+ public void setWindowWallpaperDisplayOffsetLocked(WindowState window, int x, int y) {
+ if (window.mWallpaperDisplayOffsetX != x || window.mWallpaperDisplayOffsetY != y) {
+ window.mWallpaperDisplayOffsetX = x;
+ window.mWallpaperDisplayOffsetY = y;
+ updateWallpaperOffsetLocked(window, true);
+ }
+ }
+
public Bundle sendWindowWallpaperCommandLocked(WindowState window,
String action, int x, int y, int z, Bundle extras, boolean sync) {
if (window == mWallpaperTarget || window == mLowerWallpaperTarget
@@ -4031,10 +4068,11 @@
@Override
public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp) {
synchronized(mWindowMap) {
mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
- startY, startedCallback, scaleUp);
+ startY, targetWidth, targetHeight, startedCallback, scaleUp);
}
}
@@ -4303,20 +4341,28 @@
}
public void setAppFullscreen(IBinder token, boolean toOpaque) {
- AppWindowToken atoken = findAppWindowToken(token);
- if (atoken != null) {
- atoken.appFullscreen = toOpaque;
- setWindowOpaque(token, toOpaque);
- requestTraversal();
+ synchronized (mWindowMap) {
+ AppWindowToken atoken = findAppWindowToken(token);
+ if (atoken != null) {
+ atoken.appFullscreen = toOpaque;
+ setWindowOpaqueLocked(token, toOpaque);
+ requestTraversalLocked();
+ }
}
}
public void setWindowOpaque(IBinder token, boolean isOpaque) {
+ synchronized (mWindowMap) {
+ setWindowOpaqueLocked(token, isOpaque);
+ }
+ }
+
+ public void setWindowOpaqueLocked(IBinder token, boolean isOpaque) {
AppWindowToken wtoken = findAppWindowToken(token);
if (wtoken != null) {
WindowState win = wtoken.findMainWindow();
if (win != null) {
- win.mWinAnimator.setOpaque(isOpaque);
+ win.mWinAnimator.setOpaqueLocked(isOpaque);
}
}
}
@@ -5432,6 +5478,23 @@
}
}
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public int getCameraLensCoverState() {
+ int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY,
+ InputManagerService.SW_CAMERA_LENS_COVER);
+ if (sw > 0) {
+ // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
+ return CAMERA_LENS_COVERED;
+ } else if (sw == 0) {
+ // Switch state: AKEY_STATE_UP.
+ return CAMERA_LENS_UNCOVERED;
+ } else {
+ // Switch state: AKEY_STATE_UNKNOWN.
+ return CAMERA_LENS_COVER_ABSENT;
+ }
+ }
+
// Called by window manager policy. Not exposed externally.
@Override
public void switchKeyboardLayout(int deviceId, int direction) {
@@ -5709,7 +5772,16 @@
com.android.internal.R.bool.config_windowIsRound)
&& mContext.getResources().getBoolean(
com.android.internal.R.bool.config_windowShowCircularMask)) {
- mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
+ mH.sendMessage(mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK));
+ }
+ }
+
+ public void showEmulatorDisplayOverlayIfNeeded() {
+ if (mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay)
+ && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false)
+ && Build.HARDWARE.contains("goldfish")) {
+ mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY));
}
}
@@ -5717,12 +5789,12 @@
synchronized(mWindowMap) {
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- ">>> OPEN TRANSACTION showDisplayMask");
+ ">>> OPEN TRANSACTION showCircularMask");
SurfaceControl.openTransaction();
try {
// TODO(multi-display): support multiple displays
if (mCircularDisplayMask == null) {
- int screenOffset = (int) mContext.getResources().getDimensionPixelSize(
+ int screenOffset = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.circular_display_mask_offset);
mCircularDisplayMask = new CircularDisplayMask(
@@ -5736,7 +5808,32 @@
} finally {
SurfaceControl.closeTransaction();
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
- "<<< CLOSE TRANSACTION showDisplayMask");
+ "<<< CLOSE TRANSACTION showCircularMask");
+ }
+ }
+ }
+
+ public void showEmulatorDisplayOverlay() {
+ synchronized(mWindowMap) {
+
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION showEmulatorDisplayOverlay");
+ SurfaceControl.openTransaction();
+ try {
+ if (mEmulatorDisplayOverlay == null) {
+ mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
+ mContext,
+ getDefaultDisplayContentLocked().getDisplay(),
+ mFxSession,
+ mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_POINTER)
+ * TYPE_LAYER_MULTIPLIER + 10);
+ }
+ mEmulatorDisplayOverlay.setVisibility(true);
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay");
}
}
}
@@ -5834,7 +5931,7 @@
@Override
public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
int height, boolean force565) {
- if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
@@ -5854,7 +5951,7 @@
return null;
}
- Bitmap rawss = null;
+ Bitmap bm = null;
int maxLayer = 0;
final Rect frame = new Rect();
@@ -5995,10 +6092,8 @@
// The screenshot API does not apply the current screen rotation.
rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- final int tmp = width;
- width = height;
- height = tmp;
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
}
@@ -6024,9 +6119,9 @@
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
"Taking screenshot while rotating");
- rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
- inRotation);
- if (rawss == null) {
+ bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
+ inRotation, rot);
+ if (bm == null) {
Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
+ ") to layer " + maxLayer);
return null;
@@ -6036,17 +6131,6 @@
break;
}
- Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
- Config.RGB_565 : rawss.getConfig());
- if (DEBUG_SCREENSHOT) {
- bm.eraseColor(0xFF000000);
- }
- Matrix matrix = new Matrix();
- ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
- Canvas canvas = new Canvas(bm);
- canvas.drawBitmap(rawss, matrix, null);
- canvas.setBitmap(null);
-
if (DEBUG_SCREENSHOT) {
// TEST IF IT's ALL BLACK
int[] buffer = new int[bm.getWidth() * bm.getHeight()];
@@ -6067,9 +6151,12 @@
}
}
- rawss.recycle();
-
- return bm;
+ // Copy the screenshot bitmap to another buffer so that the gralloc backed
+ // bitmap will not have a long lifetime. Gralloc memory can be pinned or
+ // duplicated and might have a higher cost than a skia backed buffer.
+ Bitmap ret = bm.copy(bm.getConfig(),true);
+ bm.recycle();
+ return ret;
}
/**
@@ -7367,7 +7454,8 @@
public static final int NEW_ANIMATOR_SCALE = 34;
- public static final int SHOW_DISPLAY_MASK = 35;
+ public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35;
+ public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36;
@Override
public void handleMessage(Message msg) {
@@ -7763,11 +7851,16 @@
break;
}
- case SHOW_DISPLAY_MASK: {
+ case SHOW_CIRCULAR_DISPLAY_MASK: {
showCircularMask();
break;
}
+ case SHOW_EMULATOR_DISPLAY_OVERLAY: {
+ showEmulatorDisplayOverlay();
+ break;
+ }
+
case DO_ANIMATION_CALLBACK: {
try {
((IRemoteCallback)msg.obj).sendResult(null);
@@ -9337,6 +9430,9 @@
if (mCircularDisplayMask != null) {
mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
}
+ if (mEmulatorDisplayOverlay != null) {
+ mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation);
+ }
boolean focusDisplayed = false;
@@ -10863,6 +10959,12 @@
}
pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
+ if (mLastWallpaperDisplayOffsetX != Integer.MIN_VALUE
+ || mLastWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ pw.print(" mLastWallpaperDisplayOffsetX="); pw.print(mLastWallpaperDisplayOffsetX);
+ pw.print(" mLastWallpaperDisplayOffsetY=");
+ pw.println(mLastWallpaperDisplayOffsetY);
+ }
if (mInputMethodAnimLayerAdjustment != 0 ||
mWallpaperAnimLayerAdjustment != 0) {
pw.print(" mInputMethodAnimLayerAdjustment=");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e74de38..0baa2be 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -247,6 +247,11 @@
float mWallpaperXStep = -1;
float mWallpaperYStep = -1;
+ // If a window showing a wallpaper: a raw pixel offset to forcibly apply
+ // to its window; if a wallpaper window: not used.
+ int mWallpaperDisplayOffsetX = Integer.MIN_VALUE;
+ int mWallpaperDisplayOffsetY = Integer.MIN_VALUE;
+
// Wallpaper windows: pixels offset based on above variables.
int mXOffset;
int mYOffset;
@@ -1584,6 +1589,13 @@
pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
}
+ if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
+ || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
+ pw.print(prefix); pw.print("mWallpaperDisplayOffsetX=");
+ pw.print(mWallpaperDisplayOffsetX);
+ pw.print(" mWallpaperDisplayOffsetY=");
+ pw.println(mWallpaperDisplayOffsetY);
+ }
}
String makeInputChannelName() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3d4be12..dd611ce 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1526,8 +1526,9 @@
}
void setWallpaperOffset(RectF shownFrame) {
- final int left = (int) shownFrame.left;
- final int top = (int) shownFrame.top;
+ final LayoutParams attrs = mWin.getAttrs();
+ final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
+ final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
if (mSurfaceX != left || mSurfaceY != top) {
mSurfaceX = left;
mSurfaceY = top;
@@ -1556,11 +1557,11 @@
}
}
- void setOpaque(boolean isOpaque) {
+ void setOpaqueLocked(boolean isOpaque) {
if (mSurfaceControl == null) {
return;
}
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaque");
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
SurfaceControl.openTransaction();
try {
if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
@@ -1568,7 +1569,7 @@
mSurfaceControl.setOpaque(isOpaque);
} finally {
SurfaceControl.closeTransaction();
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaque");
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
}
}
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index bc866d3..65a28c0 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -21,7 +21,6 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
-#include "utils/Vector.h"
#include <usbhost/usbhost.h>
@@ -68,8 +67,6 @@
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject thiz = (jobject)client_data;
- Vector<int> interfaceValues;
- Vector<int> endpointValues;
const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
char *manufacturer = usb_device_get_manufacturer_name(device);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 8ed74be..cddca92 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -71,7 +71,7 @@
jmethodID notifyANR;
jmethodID filterInputEvent;
jmethodID interceptKeyBeforeQueueing;
- jmethodID interceptWakeMotionBeforeQueueing;
+ jmethodID interceptMotionBeforeQueueingNonInteractive;
jmethodID interceptKeyBeforeDispatching;
jmethodID dispatchUnhandledKey;
jmethodID checkInjectEventsPermission;
@@ -854,7 +854,9 @@
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ if (mInteractive) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ }
}
}
@@ -870,20 +872,22 @@
if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
if (policyFlags & POLICY_FLAG_INTERACTIVE) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
- } else if (policyFlags & POLICY_FLAG_WAKE) {
+ } else {
JNIEnv* env = jniEnv();
jint wmActions = env->CallIntMethod(mServiceObj,
- gServiceClassInfo.interceptWakeMotionBeforeQueueing,
+ gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive,
when, policyFlags);
if (checkAndClearExceptionFromCallback(env,
- "interceptWakeMotionBeforeQueueing")) {
+ "interceptMotionBeforeQueueingNonInteractive")) {
wmActions = 0;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
} else {
- policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ if (mInteractive) {
+ policyFlags |= POLICY_FLAG_PASS_TO_USER;
+ }
}
}
@@ -1441,8 +1445,8 @@
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
"interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
- GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz,
- "interceptWakeMotionBeforeQueueing", "(JI)I");
+ GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingNonInteractive, clazz,
+ "interceptMotionBeforeQueueingNonInteractive", "(JI)I");
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
"interceptKeyBeforeDispatching",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cad2772..09584f4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2996,10 +2996,12 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
- synchronized (this) {
- DevicePolicyData policy = getUserData(userHandle);
- long ident = Binder.clearCallingIdentity();
- try {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ boolean wipeData = false;
+ int identifier = 0;
+ synchronized (this) {
+ DevicePolicyData policy = getUserData(userHandle);
policy.mFailedPasswordAttempts++;
saveSettingsLocked(userHandle);
if (mHasFeature) {
@@ -3011,15 +3013,20 @@
// Wipe the user/profile associated with the policy that was violated. This
// is not necessarily calling user: if the policy that fired was from a
// managed profile rather than the main user profile, we wipe former only.
- wipeDeviceOrUserLocked(0, strictestAdmin.getUserHandle().getIdentifier());
+ wipeData = true;
+ identifier = strictestAdmin.getUserHandle().getIdentifier();
}
sendAdminCommandToSelfAndProfilesLocked(
DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
}
- } finally {
- Binder.restoreCallingIdentity(ident);
}
+ if (wipeData) {
+ // Call without holding lock.
+ wipeDeviceOrUserLocked(0, identifier);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -3654,11 +3661,15 @@
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
- if (mUserManager.getUserInfo(userHandle) == null) {
+ UserInfo info = mUserManager.getUserInfo(userHandle);
+ if (info == null) {
// User doesn't exist.
throw new IllegalArgumentException(
"Attempted to set profile owner for invalid userId: " + userHandle);
}
+ if (info.isGuest()) {
+ throw new IllegalStateException("Cannot set a profile owner on a guest");
+ }
if (who == null
|| !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index ce91f3d..6785cb8 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -626,26 +627,40 @@
return userState;
}
- private void handleUserStarted(int userId) {
- UserState userState;
- synchronized (mLock) {
- userState = getOrCreateUserStateLocked(userId);
- userState.updateIfNeededLocked();
- }
- // This is the first time we switch to this user after boot, so
- // now is the time to remove obsolete print jobs since they
- // are from the last boot and no application would query them.
- userState.removeObsoletePrintJobs();
+ private void handleUserStarted(final int userId) {
+ // This code will touch the remote print spooler which
+ // must be called off the main thread, so post the work.
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ UserState userState;
+ synchronized (mLock) {
+ userState = getOrCreateUserStateLocked(userId);
+ userState.updateIfNeededLocked();
+ }
+ // This is the first time we switch to this user after boot, so
+ // now is the time to remove obsolete print jobs since they
+ // are from the last boot and no application would query them.
+ userState.removeObsoletePrintJobs();
+ }
+ });
}
- private void handleUserStopped(int userId) {
- synchronized (mLock) {
- UserState userState = mUserStates.get(userId);
- if (userState != null) {
- userState.destroyLocked();
- mUserStates.remove(userId);
+ private void handleUserStopped(final int userId) {
+ // This code will touch the remote print spooler which
+ // must be called off the main thread, so post the work.
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ UserState userState = mUserStates.get(userId);
+ if (userState != null) {
+ userState.destroyLocked();
+ mUserStates.remove(userId);
+ }
+ }
}
- }
+ });
}
private int resolveCallingProfileParentLocked(int userId) {
@@ -730,7 +745,14 @@
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT, null,
userHandle);
- Notification.Builder builder = new Notification.Builder(mContext)
+ Context builderContext = mContext;
+ try {
+ builderContext = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+ userHandle);
+ } catch (NameNotFoundException e) {
+ // Ignore can't find the package the system is running as.
+ }
+ Notification.Builder builder = new Notification.Builder(builderContext)
.setSmallIcon(R.drawable.ic_print)
.setContentTitle(mContext.getString(R.string.print_service_installed_title,
label))
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
index fb29b6a..218f899 100644
--- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
+++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
@@ -139,7 +139,7 @@
}
@Override
- public Intent getLocalApprovalIntent() throws RemoteException {
+ public Intent createLocalApprovalIntent() throws RemoteException {
if (DEBUG) {
Log.i(LOG_TAG, "requestPermission");
}
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index dc036e2..5f639ab 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -15,9 +15,11 @@
*/
package com.android.server.usage;
+import android.app.usage.ConfigurationStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
+import android.content.res.Configuration;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -25,7 +27,9 @@
public long beginTime;
public long endTime;
public long lastTimeSaved;
- public final ArrayMap<String, UsageStats> stats = new ArrayMap<>();
+ public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>();
+ public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>();
+ public Configuration activeConfiguration;
public TimeSparseArray<UsageEvents.Event> events;
// A string cache. This is important as when we're parsing XML files, we don't want to
@@ -34,18 +38,49 @@
// strings that had identical copies in the cache.
private final ArraySet<String> mStringCache = new ArraySet<>();
+ /**
+ * Gets the UsageStats object for the given package, or creates one and adds it internally.
+ */
UsageStats getOrCreateUsageStats(String packageName) {
- UsageStats usageStats = stats.get(packageName);
+ UsageStats usageStats = packageStats.get(packageName);
if (usageStats == null) {
usageStats = new UsageStats();
- usageStats.mPackageName = packageName;
+ usageStats.mPackageName = getCachedStringRef(packageName);
usageStats.mBeginTimeStamp = beginTime;
usageStats.mEndTimeStamp = endTime;
- stats.put(packageName, usageStats);
+ packageStats.put(usageStats.mPackageName, usageStats);
}
return usageStats;
}
+ /**
+ * Gets the ConfigurationStats object for the given configuration, or creates one and adds it
+ * internally.
+ */
+ ConfigurationStats getOrCreateConfigurationStats(Configuration config) {
+ ConfigurationStats configStats = configurations.get(config);
+ if (configStats == null) {
+ configStats = new ConfigurationStats();
+ configStats.mBeginTimeStamp = beginTime;
+ configStats.mEndTimeStamp = endTime;
+ configStats.mConfiguration = config;
+ configurations.put(config, configStats);
+ }
+ return configStats;
+ }
+
+ /**
+ * Builds a UsageEvents.Event, but does not add it internally.
+ */
+ UsageEvents.Event buildEvent(String packageName, String className) {
+ UsageEvents.Event event = new UsageEvents.Event();
+ event.mPackage = getCachedStringRef(packageName);
+ if (className != null) {
+ event.mClass = getCachedStringRef(className);
+ }
+ return event;
+ }
+
void update(String packageName, long timeStamp, int eventType) {
UsageStats usageStats = getOrCreateUsageStats(packageName);
@@ -61,6 +96,28 @@
usageStats.mLastEvent = eventType;
usageStats.mLastTimeUsed = timeStamp;
usageStats.mEndTimeStamp = timeStamp;
+
+ if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
+ usageStats.mLaunchCount += 1;
+ }
+
+ endTime = timeStamp;
+ }
+
+ void updateConfigurationStats(Configuration config, long timeStamp) {
+ if (activeConfiguration != null) {
+ ConfigurationStats activeStats = configurations.get(activeConfiguration);
+ activeStats.mTotalTimeActive += timeStamp - activeStats.mLastTimeActive;
+ activeStats.mLastTimeActive = timeStamp - 1;
+ }
+
+ if (config != null) {
+ ConfigurationStats configStats = getOrCreateConfigurationStats(config);
+ configStats.mLastTimeActive = timeStamp;
+ configStats.mActivationCount += 1;
+ activeConfiguration = configStats.mConfiguration;
+ }
+
endTime = timeStamp;
}
@@ -72,13 +129,4 @@
}
return mStringCache.valueAt(index);
}
-
- UsageEvents.Event buildEvent(String packageName, String className) {
- UsageEvents.Event event = new UsageEvents.Event();
- event.mPackage = getCachedStringRef(packageName);
- if (className != null) {
- event.mClass = getCachedStringRef(className);
- }
- return event;
- }
}
diff --git a/services/usage/java/com/android/server/usage/UnixCalendar.java b/services/usage/java/com/android/server/usage/UnixCalendar.java
new file mode 100644
index 0000000..ce06a91
--- /dev/null
+++ b/services/usage/java/com/android/server/usage/UnixCalendar.java
@@ -0,0 +1,99 @@
+/**
+ * Copyright (C) 2014 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.usage.UsageStatsManager;
+
+/**
+ * A handy calendar object that knows nothing of Locale's or TimeZones. This simplifies
+ * interval book-keeping. It is *NOT* meant to be used as a user-facing calendar, as it has
+ * no concept of Locale or TimeZone.
+ */
+public class UnixCalendar {
+ private static final long DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
+ private static final long WEEK_IN_MILLIS = 7 * DAY_IN_MILLIS;
+ private static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS;
+ private static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS;
+ private long mTime;
+
+ public UnixCalendar(long time) {
+ mTime = time;
+ }
+
+ public void truncateToDay() {
+ mTime -= mTime % DAY_IN_MILLIS;
+ }
+
+ public void truncateToWeek() {
+ mTime -= mTime % WEEK_IN_MILLIS;
+ }
+
+ public void truncateToMonth() {
+ mTime -= mTime % MONTH_IN_MILLIS;
+ }
+
+ public void truncateToYear() {
+ mTime -= mTime % YEAR_IN_MILLIS;
+ }
+
+ public void addDays(int val) {
+ mTime += val * DAY_IN_MILLIS;
+ }
+
+ public void addWeeks(int val) {
+ mTime += val * WEEK_IN_MILLIS;
+ }
+
+ public void addMonths(int val) {
+ mTime += val * MONTH_IN_MILLIS;
+ }
+
+ public void addYears(int val) {
+ mTime += val * YEAR_IN_MILLIS;
+ }
+
+ public void setTimeInMillis(long time) {
+ mTime = time;
+ }
+
+ public long getTimeInMillis() {
+ return mTime;
+ }
+
+ public static void truncateTo(UnixCalendar calendar, int intervalType) {
+ switch (intervalType) {
+ case UsageStatsManager.INTERVAL_YEARLY:
+ calendar.truncateToYear();
+ break;
+
+ case UsageStatsManager.INTERVAL_MONTHLY:
+ calendar.truncateToMonth();
+ break;
+
+ case UsageStatsManager.INTERVAL_WEEKLY:
+ calendar.truncateToWeek();
+ break;
+
+ case UsageStatsManager.INTERVAL_DAILY:
+ calendar.truncateToDay();
+ break;
+
+ default:
+ throw new UnsupportedOperationException("Can't truncate date to interval " +
+ intervalType);
+ }
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index e6ce0fe..62a7ec0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -17,29 +17,34 @@
package com.android.server.usage;
import android.app.usage.TimeSparseArray;
-import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.util.AtomicFile;
import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.List;
/**
* Provides an interface to query for UsageStat data from an XML database.
*/
class UsageStatsDatabase {
+ private static final int CURRENT_VERSION = 2;
+
private static final String TAG = "UsageStatsDatabase";
private static final boolean DEBUG = UsageStatsService.DEBUG;
private final Object mLock = new Object();
private final File[] mIntervalDirs;
private final TimeSparseArray<AtomicFile>[] mSortedStatFiles;
- private final Calendar mCal;
+ private final UnixCalendar mCal;
+ private final File mVersionFile;
public UsageStatsDatabase(File dir) {
mIntervalDirs = new File[] {
@@ -48,8 +53,9 @@
new File(dir, "monthly"),
new File(dir, "yearly"),
};
+ mVersionFile = new File(dir, "version");
mSortedStatFiles = new TimeSparseArray[mIntervalDirs.length];
- mCal = Calendar.getInstance();
+ mCal = new UnixCalendar(0);
}
/**
@@ -65,6 +71,8 @@
}
}
+ checkVersionLocked();
+
final FilenameFilter backupFileFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@@ -82,7 +90,45 @@
}
for (File f : files) {
- mSortedStatFiles[i].put(Long.parseLong(f.getName()), new AtomicFile(f));
+ final AtomicFile af = new AtomicFile(f);
+ mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af);
+ }
+ }
+ }
+ }
+ }
+
+ private void checkVersionLocked() {
+ int version;
+ try (BufferedReader reader = new BufferedReader(new FileReader(mVersionFile))) {
+ version = Integer.parseInt(reader.readLine());
+ } catch (NumberFormatException | IOException e) {
+ version = 0;
+ }
+
+ if (version != CURRENT_VERSION) {
+ Slog.i(TAG, "Upgrading from version " + version + " to " + CURRENT_VERSION);
+ doUpgradeLocked(version);
+
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(mVersionFile))) {
+ writer.write(Integer.toString(CURRENT_VERSION));
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to write new version");
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void doUpgradeLocked(int thisVersion) {
+ if (thisVersion < 2) {
+ // Delete all files if we are version 0. This is a pre-release version,
+ // so this is fine.
+ Slog.i(TAG, "Deleting all usage stats files");
+ for (int i = 0; i < mIntervalDirs.length; i++) {
+ File[] files = mIntervalDirs[i].listFiles();
+ if (files != null) {
+ for (File f : files) {
+ f.delete();
}
}
}
@@ -133,33 +179,77 @@
}
/**
- * Find all {@link UsageStats} for the given range and interval type.
+ * Figures out what to extract from the given IntervalStats object.
*/
- public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
+ interface StatCombiner<T> {
+
+ /**
+ * Implementations should extract interesting from <code>stats</code> and add it
+ * to the <code>accumulatedResult</code> list.
+ *
+ * If the <code>stats</code> object is mutable, <code>mutable</code> will be true,
+ * which means you should make a copy of the data before adding it to the
+ * <code>accumulatedResult</code> list.
+ *
+ * @param stats The {@link IntervalStats} object selected.
+ * @param mutable Whether or not the data inside the stats object is mutable.
+ * @param accumulatedResult The list to which to add extracted data.
+ */
+ void combine(IntervalStats stats, boolean mutable, List<T> accumulatedResult);
+ }
+
+ /**
+ * Find all {@link IntervalStats} for the given range and interval type.
+ */
+ public <T> List<T> queryUsageStats(int intervalType, long beginTime, long endTime,
+ StatCombiner<T> combiner) {
synchronized (mLock) {
if (intervalType < 0 || intervalType >= mIntervalDirs.length) {
throw new IllegalArgumentException("Bad interval type " + intervalType);
}
- if (endTime < beginTime) {
+ final TimeSparseArray<AtomicFile> intervalStats = mSortedStatFiles[intervalType];
+
+ if (endTime <= beginTime) {
+ if (DEBUG) {
+ Slog.d(TAG, "endTime(" + endTime + ") <= beginTime(" + beginTime + ")");
+ }
return null;
}
- final int startIndex = mSortedStatFiles[intervalType].closestIndexOnOrBefore(beginTime);
+ int startIndex = intervalStats.closestIndexOnOrBefore(beginTime);
if (startIndex < 0) {
+ // All the stats available have timestamps after beginTime, which means they all
+ // match.
+ startIndex = 0;
+ }
+
+ int endIndex = intervalStats.closestIndexOnOrBefore(endTime);
+ if (endIndex < 0) {
+ // All the stats start after this range ends, so nothing matches.
+ if (DEBUG) {
+ Slog.d(TAG, "No results for this range. All stats start after.");
+ }
return null;
}
- int endIndex = mSortedStatFiles[intervalType].closestIndexOnOrAfter(endTime);
- if (endIndex < 0) {
- endIndex = mSortedStatFiles[intervalType].size() - 1;
+ if (intervalStats.keyAt(endIndex) == endTime) {
+ // The endTime is exclusive, so if we matched exactly take the one before.
+ endIndex--;
+ if (endIndex < 0) {
+ // All the stats start after this range ends, so nothing matches.
+ if (DEBUG) {
+ Slog.d(TAG, "No results for this range. All stats start after.");
+ }
+ return null;
+ }
}
try {
IntervalStats stats = new IntervalStats();
- ArrayList<UsageStats> results = new ArrayList<>();
+ ArrayList<T> results = new ArrayList<>();
for (int i = startIndex; i <= endIndex; i++) {
- final AtomicFile f = mSortedStatFiles[intervalType].valueAt(i);
+ final AtomicFile f = intervalStats.valueAt(i);
if (DEBUG) {
Slog.d(TAG, "Reading stat file " + f.getBaseFile().getAbsolutePath());
@@ -167,7 +257,7 @@
UsageStatsXml.read(f, stats);
if (beginTime < stats.endTime) {
- results.addAll(stats.stats.values());
+ combiner.combine(stats, false, results);
}
}
return results;
@@ -209,19 +299,23 @@
public void prune() {
synchronized (mLock) {
long timeNow = System.currentTimeMillis();
+ mCal.setTimeInMillis(timeNow);
+ mCal.addYears(-3);
+ pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_YEARLY],
+ mCal.getTimeInMillis());
mCal.setTimeInMillis(timeNow);
- mCal.add(Calendar.MONTH, -6);
+ mCal.addMonths(-6);
pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_MONTHLY],
mCal.getTimeInMillis());
mCal.setTimeInMillis(timeNow);
- mCal.add(Calendar.WEEK_OF_YEAR, -4);
+ mCal.addWeeks(-4);
pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_WEEKLY],
mCal.getTimeInMillis());
mCal.setTimeInMillis(timeNow);
- mCal.add(Calendar.DAY_OF_YEAR, -7);
+ mCal.addDays(-7);
pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_DAILY],
mCal.getTimeInMillis());
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 0e8b427..2dcdcc4 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.app.AppOpsManager;
+import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
@@ -30,11 +31,14 @@
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
@@ -59,9 +63,7 @@
static final boolean DEBUG = false;
private static final long TEN_SECONDS = 10 * 1000;
private static final long TWENTY_MINUTES = 20 * 60 * 1000;
- private static final long TWO_MINUTES = 2 * 60 * 1000;
private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES;
- private static final long END_TIME_DELAY = DEBUG ? 0 : TWO_MINUTES;
// Handler message types.
static final int MSG_REPORT_EVENT = 0;
@@ -75,6 +77,8 @@
private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
private File mUsageStatsDir;
+ long mRealTimeSnapshot;
+ long mSystemTimeSnapshot;
public UsageStatsService(Context context) {
super(context);
@@ -101,6 +105,9 @@
cleanUpRemovedUsersLocked();
}
+ mRealTimeSnapshot = SystemClock.elapsedRealtime();
+ mSystemTimeSnapshot = System.currentTimeMillis();
+
publishLocalService(UsageStatsManagerInternal.class, new LocalService());
publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
}
@@ -175,7 +182,7 @@
}
/**
- * Called by the Bunder stub
+ * Called by the Binder stub
*/
void shutdown() {
synchronized (mLock) {
@@ -218,8 +225,7 @@
* Called by the Binder stub.
*/
List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
- final long timeNow = System.currentTimeMillis();
- if (beginTime > timeNow) {
+ if (!validRange(beginTime, endTime)) {
return null;
}
@@ -232,15 +238,23 @@
/**
* Called by the Binder stub.
*/
+ List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
+ long endTime) {
+ if (!validRange(beginTime, endTime)) {
+ return null;
+ }
+
+ synchronized (mLock) {
+ UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId);
+ return service.queryConfigurationStats(bucketType, beginTime, endTime);
+ }
+ }
+
+ /**
+ * Called by the Binder stub.
+ */
UsageEvents queryEvents(int userId, long beginTime, long endTime) {
- final long timeNow = System.currentTimeMillis();
-
- // Adjust the endTime so that we don't query for the latest events.
- // This is to prevent apps from making decision based on what app launched them,
- // etc.
- endTime = Math.min(endTime, timeNow - END_TIME_DELAY);
-
- if (beginTime > endTime) {
+ if (!validRange(beginTime, endTime)) {
return null;
}
@@ -250,6 +264,11 @@
}
}
+ private static boolean validRange(long beginTime, long endTime) {
+ final long timeNow = System.currentTimeMillis();
+ return beginTime <= timeNow && beginTime < endTime;
+ }
+
private void flushToDiskLocked() {
final int userCount = mUserState.size();
for (int i = 0; i < userCount; i++) {
@@ -323,6 +342,28 @@
}
@Override
+ public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
+ long beginTime, long endTime, String callingPackage) throws RemoteException {
+ if (!hasPermission(callingPackage)) {
+ return null;
+ }
+
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final List<ConfigurationStats> results =
+ UsageStatsService.this.queryConfigurationStats(userId, bucketType,
+ beginTime, endTime);
+ if (results != null) {
+ return new ParceledListSlice<>(results);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return null;
+ }
+
+ @Override
public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
if (!hasPermission(callingPackage)) {
return null;
@@ -345,9 +386,16 @@
*/
private class LocalService extends UsageStatsManagerInternal {
+ /**
+ * The system may have its time change, so at least make sure the events
+ * are monotonic in order.
+ */
+ private long computeMonotonicSystemTime(long realTime) {
+ return (realTime - mRealTimeSnapshot) + mSystemTimeSnapshot;
+ }
+
@Override
- public void reportEvent(ComponentName component, int userId,
- long timeStamp, int eventType) {
+ public void reportEvent(ComponentName component, int userId, int eventType) {
if (component == null) {
Slog.w(TAG, "Event reported without a component name");
return;
@@ -356,12 +404,27 @@
UsageEvents.Event event = new UsageEvents.Event();
event.mPackage = component.getPackageName();
event.mClass = component.getClassName();
- event.mTimeStamp = timeStamp;
+ event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime());
event.mEventType = eventType;
mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
}
@Override
+ public void reportConfigurationChange(Configuration config, int userId) {
+ if (config == null) {
+ Slog.w(TAG, "Configuration event reported with a null config");
+ return;
+ }
+
+ UsageEvents.Event event = new UsageEvents.Event();
+ event.mPackage = "android";
+ event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime());
+ event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
+ event.mConfiguration = new Configuration(config);
+ mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
+ }
+
+ @Override
public void prepareShutdown() {
// This method *WILL* do IO work, but we must block until it is finished or else
// we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
diff --git a/services/usage/java/com/android/server/usage/UsageStatsUtils.java b/services/usage/java/com/android/server/usage/UsageStatsUtils.java
deleted file mode 100644
index dd5f3b9..0000000
--- a/services/usage/java/com/android/server/usage/UsageStatsUtils.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Copyright (C) 2014 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.usage.UsageStatsManager;
-
-import java.util.Calendar;
-
-/**
- * A collection of utility methods used by the UsageStatsService and accompanying classes.
- */
-final class UsageStatsUtils {
- private UsageStatsUtils() {}
-
- /**
- * Truncates the date to the given UsageStats bucket. For example, if the bucket is
- * {@link UsageStatsManager#INTERVAL_YEARLY}, the date is truncated to the 1st day of the year,
- * with the time set to 00:00:00.
- *
- * @param bucket The UsageStats bucket to truncate to.
- * @param cal The date to truncate.
- */
- public static void truncateDateTo(int bucket, Calendar cal) {
- cal.set(Calendar.HOUR_OF_DAY, 0);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.SECOND, 0);
- cal.set(Calendar.MILLISECOND, 0);
-
- switch (bucket) {
- case UsageStatsManager.INTERVAL_YEARLY:
- cal.set(Calendar.DAY_OF_YEAR, 0);
- break;
-
- case UsageStatsManager.INTERVAL_MONTHLY:
- cal.set(Calendar.DAY_OF_MONTH, 0);
- break;
-
- case UsageStatsManager.INTERVAL_WEEKLY:
- cal.set(Calendar.DAY_OF_WEEK, 0);
- break;
-
- case UsageStatsManager.INTERVAL_DAILY:
- break;
-
- default:
- throw new UnsupportedOperationException("Can't truncate date to bucket " + bucket);
- }
- }
-}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 48881d0..9ce6d63 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -37,10 +37,15 @@
private static final String USAGESTATS_TAG = "usagestats";
private static final String VERSION_ATTR = "version";
+ public static long parseBeginTime(AtomicFile file) {
+ return Long.parseLong(file.getBaseFile().getName());
+ }
+
public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
try {
FileInputStream in = file.openRead();
try {
+ statsOut.beginTime = parseBeginTime(file);
read(in, statsOut);
statsOut.lastTimeSaved = file.getLastModifiedTime();
} finally {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 374429a..ef95a7b 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -15,16 +15,17 @@
*/
package com.android.server.usage;
-import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import android.app.usage.ConfigurationStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
-import android.content.ComponentName;
+import android.content.res.Configuration;
import java.io.IOException;
import java.net.ProtocolException;
@@ -33,103 +34,144 @@
* UsageStats reader/writer for version 1 of the XML format.
*/
final class UsageStatsXmlV1 {
- private static final String BEGIN_TIME_ATTR = "beginTime";
- private static final String END_TIME_ATTR = "endTime";
+ private static final String PACKAGES_TAG = "packages";
private static final String PACKAGE_TAG = "package";
- private static final String NAME_ATTR = "name";
+
+ private static final String CONFIGURATIONS_TAG = "configurations";
+ private static final String CONFIG_TAG = "config";
+
+ private static final String EVENT_LOG_TAG = "event-log";
+ private static final String EVENT_TAG = "event";
+
+ // Attributes
private static final String PACKAGE_ATTR = "package";
private static final String CLASS_ATTR = "class";
- private static final String TOTAL_TIME_ACTIVE_ATTR = "totalTimeActive";
- private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+ private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
+ private static final String COUNT_ATTR = "count";
+ private static final String ACTIVE_ATTR = "active";
private static final String LAST_EVENT_ATTR = "lastEvent";
- private static final String EVENT_LOG_TAG = "event-log";
private static final String TYPE_ATTR = "type";
+
+ // Time attributes stored as an offset of the beginTime.
+ private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+ private static final String END_TIME_ATTR = "endTime";
private static final String TIME_ATTR = "time";
- private static UsageStats readNextUsageStats(XmlPullParser parser)
+ private static void loadUsageStats(XmlPullParser parser, IntervalStats statsOut)
throws XmlPullParserException, IOException {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- XmlUtils.nextElement(parser);
+ final String pkg = parser.getAttributeValue(null, PACKAGE_ATTR);
+ if (pkg == null) {
+ throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
}
- if (parser.getEventType() != XmlPullParser.START_TAG ||
- !parser.getName().equals(PACKAGE_TAG)) {
- return null;
- }
+ final UsageStats stats = statsOut.getOrCreateUsageStats(pkg);
- final String name = parser.getAttributeValue(null, NAME_ATTR);
- if (name == null) {
- throw new ProtocolException("no " + NAME_ATTR + " attribute present");
- }
+ // Apply the offset to the beginTime to find the absolute time.
+ stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
+ parser, LAST_TIME_ACTIVE_ATTR);
- UsageStats stats = new UsageStats();
- stats.mPackageName = name;
stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
- stats.mLastTimeUsed = XmlUtils.readLongAttribute(parser, LAST_TIME_ACTIVE_ATTR);
stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
- XmlUtils.skipCurrentTag(parser);
- return stats;
}
- private static UsageEvents.Event readNextEvent(XmlPullParser parser, IntervalStats statsOut)
+ private static void loadConfigStats(XmlPullParser parser, IntervalStats statsOut)
throws XmlPullParserException, IOException {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- XmlUtils.nextElement(parser);
- }
+ final Configuration config = new Configuration();
+ Configuration.readXmlAttrs(parser, config);
- if (parser.getEventType() != XmlPullParser.START_TAG ||
- !parser.getName().equals(EVENT_LOG_TAG)) {
- return null;
- }
+ final ConfigurationStats configStats = statsOut.getOrCreateConfigurationStats(config);
- String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR);
- String className;
+ // Apply the offset to the beginTime to find the absolute time.
+ configStats.mLastTimeActive = statsOut.beginTime + XmlUtils.readLongAttribute(
+ parser, LAST_TIME_ACTIVE_ATTR);
+
+ configStats.mTotalTimeActive = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
+ configStats.mActivationCount = XmlUtils.readIntAttribute(parser, COUNT_ATTR);
+ if (XmlUtils.readBooleanAttribute(parser, ACTIVE_ATTR)) {
+ statsOut.activeConfiguration = configStats.mConfiguration;
+ }
+ }
+
+ private static void loadEvent(XmlPullParser parser, IntervalStats statsOut)
+ throws XmlPullParserException, IOException {
+ final String packageName = XmlUtils.readStringAttribute(parser, PACKAGE_ATTR);
if (packageName == null) {
- // Try getting the component name if it exists.
- final String componentName = XmlUtils.readStringAttribute(parser, NAME_ATTR);
- if (componentName == null) {
- throw new ProtocolException("no " + NAME_ATTR + " or " + PACKAGE_ATTR +
- " attribute present");
- }
- ComponentName component = ComponentName.unflattenFromString(componentName);
- if (component == null) {
- throw new ProtocolException("ComponentName " + componentName + " is invalid");
- }
-
- packageName = component.getPackageName();
- className = component.getClassName();
- } else {
- className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
+ throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
}
- UsageEvents.Event event = statsOut.buildEvent(packageName, className);
+ final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
+
+ final UsageEvents.Event event = statsOut.buildEvent(packageName, className);
+
+ // Apply the offset to the beginTime to find the absolute time of this event.
+ event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
+
event.mEventType = XmlUtils.readIntAttribute(parser, TYPE_ATTR);
- event.mTimeStamp = XmlUtils.readLongAttribute(parser, TIME_ATTR);
- XmlUtils.skipCurrentTag(parser);
- return event;
- }
-
- private static void writeUsageStats(FastXmlSerializer serializer, UsageStats stats)
- throws IOException {
- serializer.startTag(null, PACKAGE_TAG);
- serializer.attribute(null, NAME_ATTR, stats.mPackageName);
- serializer.attribute(null, TOTAL_TIME_ACTIVE_ATTR,
- Long.toString(stats.mTotalTimeInForeground));
- serializer.attribute(null, LAST_TIME_ACTIVE_ATTR, Long.toString(stats.mLastTimeUsed));
- serializer.attribute(null, LAST_EVENT_ATTR, Integer.toString(stats.mLastEvent));
- serializer.endTag(null, PACKAGE_TAG);
- }
-
- private static void writeEvent(FastXmlSerializer serializer, UsageEvents.Event event)
- throws IOException {
- serializer.startTag(null, EVENT_LOG_TAG);
- serializer.attribute(null, PACKAGE_ATTR, event.mPackage);
- if (event.mClass != null) {
- serializer.attribute(null, CLASS_ATTR, event.mClass);
+ if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+ event.mConfiguration = new Configuration();
+ Configuration.readXmlAttrs(parser, event.mConfiguration);
}
- serializer.attribute(null, TYPE_ATTR, Integer.toString(event.getEventType()));
- serializer.attribute(null, TIME_ATTR, Long.toString(event.getTimeStamp()));
- serializer.endTag(null, EVENT_LOG_TAG);
+
+ if (statsOut.events == null) {
+ statsOut.events = new TimeSparseArray<>();
+ }
+ statsOut.events.put(event.mTimeStamp, event);
+ }
+
+ private static void writeUsageStats(XmlSerializer xml, final IntervalStats stats,
+ final UsageStats usageStats) throws IOException {
+ xml.startTag(null, PACKAGE_TAG);
+
+ // Write the time offset.
+ XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
+ usageStats.mLastTimeUsed - stats.beginTime);
+
+ XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
+ XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+ XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
+
+ xml.endTag(null, PACKAGE_TAG);
+ }
+
+ private static void writeConfigStats(XmlSerializer xml, final IntervalStats stats,
+ final ConfigurationStats configStats, boolean isActive) throws IOException {
+ xml.startTag(null, CONFIG_TAG);
+
+ // Write the time offset.
+ XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
+ configStats.mLastTimeActive - stats.beginTime);
+
+ XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, configStats.mTotalTimeActive);
+ XmlUtils.writeIntAttribute(xml, COUNT_ATTR, configStats.mActivationCount);
+ if (isActive) {
+ XmlUtils.writeBooleanAttribute(xml, ACTIVE_ATTR, true);
+ }
+
+ // Now write the attributes representing the configuration object.
+ Configuration.writeXmlAttrs(xml, configStats.mConfiguration);
+
+ xml.endTag(null, CONFIG_TAG);
+ }
+
+ private static void writeEvent(XmlSerializer xml, final IntervalStats stats,
+ final UsageEvents.Event event) throws IOException {
+ xml.startTag(null, EVENT_TAG);
+
+ // Store the time offset.
+ XmlUtils.writeLongAttribute(xml, TIME_ATTR, event.mTimeStamp - stats.beginTime);
+
+ XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, event.mPackage);
+ if (event.mClass != null) {
+ XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
+ }
+ XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
+
+ if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE
+ && event.mConfiguration != null) {
+ Configuration.writeXmlAttrs(xml, event.mConfiguration);
+ }
+
+ xml.endTag(null, EVENT_TAG);
}
/**
@@ -141,55 +183,74 @@
*/
public static void read(XmlPullParser parser, IntervalStats statsOut)
throws XmlPullParserException, IOException {
- statsOut.stats.clear();
+ statsOut.packageStats.clear();
+ statsOut.configurations.clear();
+ statsOut.activeConfiguration = null;
if (statsOut.events != null) {
statsOut.events.clear();
}
- statsOut.beginTime = XmlUtils.readLongAttribute(parser, BEGIN_TIME_ATTR);
statsOut.endTime = XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
- XmlUtils.nextElement(parser);
- UsageStats pkgStats;
- while ((pkgStats = readNextUsageStats(parser)) != null) {
- pkgStats.mBeginTimeStamp = statsOut.beginTime;
- pkgStats.mEndTimeStamp = statsOut.endTime;
- statsOut.stats.put(pkgStats.mPackageName, pkgStats);
- }
-
- UsageEvents.Event event;
- while ((event = readNextEvent(parser, statsOut)) != null) {
- if (statsOut.events == null) {
- statsOut.events = new TimeSparseArray<>();
+ int eventCode;
+ int outerDepth = parser.getDepth();
+ while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (eventCode != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (eventCode != XmlPullParser.START_TAG) {
+ continue;
}
- statsOut.events.put(event.getTimeStamp(), event);
+
+ final String tag = parser.getName();
+ switch (tag) {
+ case PACKAGE_TAG:
+ loadUsageStats(parser, statsOut);
+ break;
+
+ case CONFIG_TAG:
+ loadConfigStats(parser, statsOut);
+ break;
+
+ case EVENT_TAG:
+ loadEvent(parser, statsOut);
+ break;
+ }
}
}
/**
- * Writes the stats object to an XML file. The {@link FastXmlSerializer}
+ * Writes the stats object to an XML file. The {@link XmlSerializer}
* has already written the <code><usagestats></code> tag, but attributes may still
* be added.
*
- * @param serializer The serializer to which to write the stats data.
+ * @param xml The serializer to which to write the packageStats data.
* @param stats The stats object to write to the XML file.
*/
- public static void write(FastXmlSerializer serializer, IntervalStats stats) throws IOException {
- serializer.attribute(null, BEGIN_TIME_ATTR, Long.toString(stats.beginTime));
- serializer.attribute(null, END_TIME_ATTR, Long.toString(stats.endTime));
+ public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
+ XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
- final int statsCount = stats.stats.size();
+ xml.startTag(null, PACKAGES_TAG);
+ final int statsCount = stats.packageStats.size();
for (int i = 0; i < statsCount; i++) {
- writeUsageStats(serializer, stats.stats.valueAt(i));
+ writeUsageStats(xml, stats, stats.packageStats.valueAt(i));
}
+ xml.endTag(null, PACKAGES_TAG);
- if (stats.events != null) {
- final int eventCount = stats.events.size();
- for (int i = 0; i < eventCount; i++) {
- writeEvent(serializer, stats.events.valueAt(i));
- }
+
+ xml.startTag(null, CONFIGURATIONS_TAG);
+ final int configCount = stats.configurations.size();
+ for (int i = 0; i < configCount; i++) {
+ boolean active = stats.activeConfiguration.equals(stats.configurations.keyAt(i));
+ writeConfigStats(xml, stats, stats.configurations.valueAt(i), active);
}
+ xml.endTag(null, CONFIGURATIONS_TAG);
+
+ xml.startTag(null, EVENT_LOG_TAG);
+ final int eventCount = stats.events != null ? stats.events.size() : 0;
+ for (int i = 0; i < eventCount; i++) {
+ writeEvent(xml, stats, stats.events.valueAt(i));
+ }
+ xml.endTag(null, EVENT_LOG_TAG);
}
private UsageStatsXmlV1() {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 6951590..2769666 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -16,19 +16,22 @@
package com.android.server.usage;
+import android.app.usage.ConfigurationStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
+import android.content.res.Configuration;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Calendar;
import java.util.List;
/**
@@ -43,7 +46,7 @@
private final UsageStatsDatabase mDatabase;
private final IntervalStats[] mCurrentStats;
private boolean mStatsChanged = false;
- private final Calendar mDailyExpiryDate;
+ private final UnixCalendar mDailyExpiryDate;
private final StatsUpdatedListener mListener;
private final String mLogPrefix;
@@ -52,7 +55,7 @@
}
UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) {
- mDailyExpiryDate = Calendar.getInstance();
+ mDailyExpiryDate = new UnixCalendar(0);
mDatabase = new UsageStatsDatabase(usageStatsDir);
mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
mListener = listener;
@@ -62,6 +65,7 @@
void init() {
mDatabase.init();
+ final long timeNow = System.currentTimeMillis();
int nullCount = 0;
for (int i = 0; i < mCurrentStats.length; i++) {
mCurrentStats[i] = mDatabase.getLatestUsageStats(i);
@@ -69,6 +73,11 @@
// Find out how many intervals we don't have data for.
// Ideally it should be all or none.
nullCount++;
+ } else if (mCurrentStats[i].beginTime > timeNow) {
+ Slog.e(TAG, mLogPrefix + "Interval " + i + " has stat in the future " +
+ mCurrentStats[i].beginTime);
+ mCurrentStats[i] = null;
+ nullCount++;
}
}
@@ -90,17 +99,18 @@
// that is reported.
mDailyExpiryDate.setTimeInMillis(
mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime);
- mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1);
- UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate);
- Slog.i(TAG, mLogPrefix + "Rollover scheduled for "
- + sDateFormat.format(mDailyExpiryDate.getTime()));
+ mDailyExpiryDate.addDays(1);
+ mDailyExpiryDate.truncateToDay();
+ Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
+ sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) +
+ "(" + mDailyExpiryDate.getTimeInMillis() + ")");
}
// Now close off any events that were open at the time this was saved.
for (IntervalStats stat : mCurrentStats) {
- final int pkgCount = stat.stats.size();
+ final int pkgCount = stat.packageStats.size();
for (int i = 0; i < pkgCount; i++) {
- UsageStats pkgStats = stat.stats.valueAt(i);
+ UsageStats pkgStats = stat.packageStats.valueAt(i);
if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
stat.update(pkgStats.mPackageName, stat.lastTimeSaved,
@@ -108,121 +118,202 @@
notifyStatsChanged();
}
}
+
+ stat.updateConfigurationStats(null, stat.lastTimeSaved);
}
}
void reportEvent(UsageEvents.Event event) {
if (DEBUG) {
Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
- + "[" + event.getTimeStamp() + "]: "
- + eventToString(event.getEventType()));
+ + "[" + event.mTimeStamp + "]: "
+ + eventToString(event.mEventType));
}
- if (event.getTimeStamp() >= mDailyExpiryDate.getTimeInMillis()) {
+ if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
// Need to rollover
rolloverStats();
}
- if (mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events == null) {
- mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events = new TimeSparseArray<>();
+ final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY];
+
+ final Configuration newFullConfig = event.mConfiguration;
+ if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE &&
+ currentDailyStats.activeConfiguration != null) {
+ // Make the event configuration a delta.
+ event.mConfiguration = Configuration.generateDelta(
+ currentDailyStats.activeConfiguration, newFullConfig);
}
- mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events.put(event.getTimeStamp(), event);
+
+ // Add the event to the daily list.
+ if (currentDailyStats.events == null) {
+ currentDailyStats.events = new TimeSparseArray<>();
+ }
+ currentDailyStats.events.put(event.mTimeStamp, event);
for (IntervalStats stats : mCurrentStats) {
- stats.update(event.mPackage, event.getTimeStamp(),
- event.getEventType());
+ if (event.mEventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+ stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
+ } else {
+ stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+ }
}
notifyStatsChanged();
}
- List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) {
- if (bucketType == UsageStatsManager.INTERVAL_BEST) {
- bucketType = mDatabase.findBestFitBucket(beginTime, endTime);
+ private static final StatCombiner<UsageStats> sUsageStatsCombiner =
+ new StatCombiner<UsageStats>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<UsageStats> accResult) {
+ if (!mutable) {
+ accResult.addAll(stats.packageStats.values());
+ return;
+ }
+
+ final int statCount = stats.packageStats.size();
+ for (int i = 0; i < statCount; i++) {
+ accResult.add(new UsageStats(stats.packageStats.valueAt(i)));
+ }
+ }
+ };
+
+ private static final StatCombiner<ConfigurationStats> sConfigStatsCombiner =
+ new StatCombiner<ConfigurationStats>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<ConfigurationStats> accResult) {
+ if (!mutable) {
+ accResult.addAll(stats.configurations.values());
+ return;
+ }
+
+ final int configCount = stats.configurations.size();
+ for (int i = 0; i < configCount; i++) {
+ accResult.add(new ConfigurationStats(stats.configurations.valueAt(i)));
+ }
+ }
+ };
+
+ /**
+ * Generic query method that selects the appropriate IntervalStats for the specified time range
+ * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner}
+ * provided to select the stats to use from the IntervalStats object.
+ */
+ private <T> List<T> queryStats(int intervalType, final long beginTime, final long endTime,
+ StatCombiner<T> combiner) {
+ if (intervalType == UsageStatsManager.INTERVAL_BEST) {
+ intervalType = mDatabase.findBestFitBucket(beginTime, endTime);
+ if (intervalType < 0) {
+ // Nothing saved to disk yet, so every stat is just as equal (no rollover has
+ // occurred.
+ intervalType = UsageStatsManager.INTERVAL_DAILY;
+ }
}
- if (bucketType < 0 || bucketType >= mCurrentStats.length) {
+ if (intervalType < 0 || intervalType >= mCurrentStats.length) {
if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "Bad bucketType used " + bucketType);
+ Slog.d(TAG, mLogPrefix + "Bad intervalType used " + intervalType);
}
return null;
}
- if (beginTime >= mCurrentStats[bucketType].endTime) {
- if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
- + mCurrentStats[bucketType].endTime);
- }
- // Nothing newer available.
- return null;
-
- } else if (beginTime >= mCurrentStats[bucketType].beginTime) {
- if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "Returning in-memory stats for bucket " + bucketType);
- }
- // Fast path for retrieving in-memory state.
- ArrayList<UsageStats> results = new ArrayList<>();
- final int packageCount = mCurrentStats[bucketType].stats.size();
- for (int i = 0; i < packageCount; i++) {
- results.add(new UsageStats(mCurrentStats[bucketType].stats.valueAt(i)));
- }
- return results;
- }
-
- // Flush any changes that were made to disk before we do a disk query.
- // If we're not grabbing the ongoing stats, no need to persist.
- persistActiveStats();
+ final IntervalStats currentStats = mCurrentStats[intervalType];
if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "SELECT * FROM " + bucketType + " WHERE beginTime >= "
+ Slog.d(TAG, mLogPrefix + "SELECT * FROM " + intervalType + " WHERE beginTime >= "
+ beginTime + " AND endTime < " + endTime);
}
- final List<UsageStats> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime);
+ if (beginTime >= currentStats.endTime) {
+ if (DEBUG) {
+ Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
+ + currentStats.endTime);
+ }
+ // Nothing newer available.
+ return null;
+ }
+
+ // Truncate the endTime to just before the in-memory stats. Then, we'll append the
+ // in-memory stats to the results (if necessary) so as to avoid writing to disk too
+ // often.
+ final long truncatedEndTime = Math.min(currentStats.beginTime, endTime);
+
+ // Get the stats from disk.
+ List<T> results = mDatabase.queryUsageStats(intervalType, beginTime,
+ truncatedEndTime, combiner);
if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "Results: " + (results == null ? 0 : results.size()));
+ Slog.d(TAG, "Got " + (results != null ? results.size() : 0) + " results from disk");
+ Slog.d(TAG, "Current stats beginTime=" + currentStats.beginTime +
+ " endTime=" + currentStats.endTime);
+ }
+
+ // Now check if the in-memory stats match the range and add them if they do.
+ if (beginTime < currentStats.endTime && endTime > currentStats.beginTime) {
+ if (DEBUG) {
+ Slog.d(TAG, mLogPrefix + "Returning in-memory stats");
+ }
+
+ if (results == null) {
+ results = new ArrayList<>();
+ }
+ combiner.combine(currentStats, true, results);
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, mLogPrefix + "Results: " + (results != null ? results.size() : 0));
}
return results;
}
- UsageEvents queryEvents(long beginTime, long endTime) {
- if (endTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime) {
- if (beginTime > mCurrentStats[UsageStatsManager.INTERVAL_DAILY].endTime) {
- return null;
- }
+ List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) {
+ return queryStats(bucketType, beginTime, endTime, sUsageStatsCombiner);
+ }
- TimeSparseArray<UsageEvents.Event> events =
- mCurrentStats[UsageStatsManager.INTERVAL_DAILY].events;
- if (events == null) {
- return null;
- }
+ List<ConfigurationStats> queryConfigurationStats(int bucketType, long beginTime, long endTime) {
+ return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
+ }
- final int startIndex = events.closestIndexOnOrAfter(beginTime);
- if (startIndex < 0) {
- return null;
- }
+ UsageEvents queryEvents(final long beginTime, final long endTime) {
+ final ArraySet<String> names = new ArraySet<>();
+ List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
+ beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
+ @Override
+ public void combine(IntervalStats stats, boolean mutable,
+ List<UsageEvents.Event> accumulatedResult) {
+ if (stats.events == null) {
+ return;
+ }
- ArraySet<String> names = new ArraySet<>();
- ArrayList<UsageEvents.Event> results = new ArrayList<>();
- final int size = events.size();
- for (int i = startIndex; i < size; i++) {
- if (events.keyAt(i) >= endTime) {
- break;
- }
- final UsageEvents.Event event = events.valueAt(i);
- names.add(event.mPackage);
- if (event.mClass != null) {
- names.add(event.mClass);
- }
- results.add(event);
- }
- String[] table = names.toArray(new String[names.size()]);
- Arrays.sort(table);
- return new UsageEvents(results, table);
+ final int startIndex = stats.events.closestIndexOnOrAfter(beginTime);
+ if (startIndex < 0) {
+ return;
+ }
+
+ final int size = stats.events.size();
+ for (int i = startIndex; i < size; i++) {
+ if (stats.events.keyAt(i) >= endTime) {
+ return;
+ }
+
+ final UsageEvents.Event event = stats.events.valueAt(i);
+ names.add(event.mPackage);
+ if (event.mClass != null) {
+ names.add(event.mClass);
+ }
+ accumulatedResult.add(event);
+ }
+ }
+ });
+
+ if (results == null || results.isEmpty()) {
+ return null;
}
- // TODO(adamlesinski): Query the previous days.
- return null;
+ String[] table = names.toArray(new String[names.size()]);
+ Arrays.sort(table);
+ return new UsageEvents(results, table);
}
void persistActiveStats() {
@@ -245,19 +336,23 @@
// Finish any ongoing events with an END_OF_DAY event. Make a note of which components
// need a new CONTINUE_PREVIOUS_DAY entry.
+ final Configuration previousConfig =
+ mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
ArraySet<String> continuePreviousDay = new ArraySet<>();
for (IntervalStats stat : mCurrentStats) {
- final int pkgCount = stat.stats.size();
+ final int pkgCount = stat.packageStats.size();
for (int i = 0; i < pkgCount; i++) {
- UsageStats pkgStats = stat.stats.valueAt(i);
+ UsageStats pkgStats = stat.packageStats.valueAt(i);
if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
continuePreviousDay.add(pkgStats.mPackageName);
- stat.update(pkgStats.mPackageName,
- mDailyExpiryDate.getTimeInMillis() - 1, UsageEvents.Event.END_OF_DAY);
+ stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1,
+ UsageEvents.Event.END_OF_DAY);
mStatsChanged = true;
}
}
+
+ stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
}
persistActiveStats();
@@ -267,9 +362,10 @@
final int continueCount = continuePreviousDay.size();
for (int i = 0; i < continueCount; i++) {
String name = continuePreviousDay.valueAt(i);
+ final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
for (IntervalStats stat : mCurrentStats) {
- stat.update(name, mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime,
- UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+ stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+ stat.updateConfigurationStats(previousConfig, beginTime);
mStatsChanged = true;
}
}
@@ -290,54 +386,53 @@
private void loadActiveStats() {
final long timeNow = System.currentTimeMillis();
- Calendar tempCal = mDailyExpiryDate;
- for (int bucketType = 0; bucketType < mCurrentStats.length; bucketType++) {
+ final UnixCalendar tempCal = mDailyExpiryDate;
+ for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
tempCal.setTimeInMillis(timeNow);
- UsageStatsUtils.truncateDateTo(bucketType, tempCal);
+ UnixCalendar.truncateTo(tempCal, intervalType);
- if (mCurrentStats[bucketType] != null &&
- mCurrentStats[bucketType].beginTime == tempCal.getTimeInMillis()) {
+ if (mCurrentStats[intervalType] != null &&
+ mCurrentStats[intervalType].beginTime == tempCal.getTimeInMillis()) {
// These are the same, no need to load them (in memory stats are always newer
// than persisted stats).
continue;
}
- final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(bucketType);
- if (lastBeginTime >= tempCal.getTimeInMillis()) {
+ final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(intervalType);
+ if (lastBeginTime > timeNow) {
+ Slog.e(TAG, mLogPrefix + "Latest usage stats for interval " +
+ intervalType + " begins in the future");
+ mCurrentStats[intervalType] = null;
+ } else if (lastBeginTime >= tempCal.getTimeInMillis()) {
if (DEBUG) {
- Slog.d(TAG, mLogPrefix + "Loading existing stats (" + lastBeginTime +
- ") for bucket " + bucketType);
+ Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
+ sDateFormat.format(lastBeginTime) + "(" + lastBeginTime +
+ ") for interval " + intervalType);
}
- mCurrentStats[bucketType] = mDatabase.getLatestUsageStats(bucketType);
- if (DEBUG) {
- if (mCurrentStats[bucketType] != null) {
- Slog.d(TAG, mLogPrefix + "Found " +
- (mCurrentStats[bucketType].events == null ?
- 0 : mCurrentStats[bucketType].events.size()) +
- " events");
- }
- }
+ mCurrentStats[intervalType] = mDatabase.getLatestUsageStats(intervalType);
} else {
- mCurrentStats[bucketType] = null;
+ mCurrentStats[intervalType] = null;
}
- if (mCurrentStats[bucketType] == null) {
+ if (mCurrentStats[intervalType] == null) {
if (DEBUG) {
- Slog.d(TAG, "Creating new stats (" + tempCal.getTimeInMillis() +
- ") for bucket " + bucketType);
+ Slog.d(TAG, "Creating new stats @ " +
+ sDateFormat.format(tempCal.getTimeInMillis()) + "(" +
+ tempCal.getTimeInMillis() + ") for interval " + intervalType);
}
- mCurrentStats[bucketType] = new IntervalStats();
- mCurrentStats[bucketType].beginTime = tempCal.getTimeInMillis();
- mCurrentStats[bucketType].endTime = timeNow;
+ mCurrentStats[intervalType] = new IntervalStats();
+ mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis();
+ mCurrentStats[intervalType].endTime = timeNow;
}
}
mStatsChanged = false;
mDailyExpiryDate.setTimeInMillis(timeNow);
- mDailyExpiryDate.add(Calendar.DAY_OF_YEAR, 1);
- UsageStatsUtils.truncateDateTo(UsageStatsManager.INTERVAL_DAILY, mDailyExpiryDate);
- Slog.i(TAG, mLogPrefix + "Rollover scheduled for "
- + sDateFormat.format(mDailyExpiryDate.getTime()));
+ mDailyExpiryDate.addDays(1);
+ mDailyExpiryDate.truncateToDay();
+ Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
+ sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" +
+ tempCal.getTimeInMillis() + ")");
}
@@ -353,6 +448,8 @@
return "END_OF_DAY";
case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
return "CONTINUE_PREVIOUS_DAY";
+ case UsageEvents.Event.CONFIGURATION_CHANGE:
+ return "CONFIGURATION_CHANGE";
default:
return "UNKNOWN";
}
diff --git a/telecomm/java/android/telecomm/AudioState.java b/telecomm/java/android/telecomm/AudioState.java
index a5fda79..314704b 100644
--- a/telecomm/java/android/telecomm/AudioState.java
+++ b/telecomm/java/android/telecomm/AudioState.java
@@ -34,7 +34,7 @@
/** Direct the audio stream through a wired headset. */
public static final int ROUTE_WIRED_HEADSET = 0x00000004;
- /** Direct the audio stream through the device's spakerphone. */
+ /** Direct the audio stream through the device's speakerphone. */
public static final int ROUTE_SPEAKER = 0x00000008;
/**
@@ -43,7 +43,10 @@
*/
public static final int ROUTE_WIRED_OR_EARPIECE = ROUTE_EARPIECE | ROUTE_WIRED_HEADSET;
- /** Bit mask of all possible audio routes. */
+ /** Bit mask of all possible audio routes.
+ *
+ * @hide
+ */
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
ROUTE_SPEAKER;
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 5bf0855..c3aa2a0 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -517,6 +517,20 @@
}
/**
+ * Merges the calls within this conference. See {@link PhoneCapabilities#MERGE_CONFERENCE}.
+ */
+ public void mergeConference() {
+ mInCallAdapter.mergeConference(mTelecommCallId);
+ }
+
+ /**
+ * Swaps the calls within this conference. See {@link PhoneCapabilities#SWAP_CONFERENCE}.
+ */
+ public void swapConference() {
+ mInCallAdapter.swapConference(mTelecommCallId);
+ }
+
+ /**
* Obtains the parent of this {@code Call} in a conference, if any.
*
* @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 879ff66..f9c3ac3 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -54,7 +54,7 @@
mPhoneAccount = phoneAccount;
}
- public final PhoneAccountHandle getPhoneAccount() {
+ public final PhoneAccountHandle getPhoneAccountHandle() {
return mPhoneAccount;
}
@@ -93,6 +93,18 @@
public void onUnhold() {}
/**
+ * Invoked when the child calls should be merged. Only invoked if the conference contains the
+ * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
+ */
+ public void onMerge() {}
+
+ /**
+ * Invoked when the child calls should be swapped. Only invoked if the conference contains the
+ * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
+ */
+ public void onSwap() {}
+
+ /**
* Sets state to be on hold.
*/
public final void setOnHold() {
@@ -141,7 +153,7 @@
* @param connection The connection to add.
* @return True if the connection was successfully added.
*/
- public boolean addConnection(Connection connection) {
+ public final boolean addConnection(Connection connection) {
if (connection != null && !mChildConnections.contains(connection)) {
if (connection.setConference(this)) {
mChildConnections.add(connection);
@@ -160,7 +172,7 @@
* @param connection The connection to remove.
* @return True if the connection was successfully removed.
*/
- public void removeConnection(Connection connection) {
+ public final void removeConnection(Connection connection) {
Log.d(this, "removing %s from %s", connection, mChildConnections);
if (connection != null && mChildConnections.remove(connection)) {
connection.resetConference();
@@ -171,9 +183,9 @@
}
/**
- * Tears down the conference object and any of it's current connections.
+ * Tears down the conference object and any of its current connections.
*/
- public void destroy() {
+ public final void destroy() {
Log.d(this, "destroying conference : %s", this);
// Tear down the children.
for (Connection connection : mChildConnections) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 4d6e267..03db1c3 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -139,7 +139,7 @@
*/
public static final int SESSION_MODIFY_REQUEST_INVALID = 3;
- private static final int MSG_SET_VIDEO_LISTENER = 1;
+ private static final int MSG_SET_VIDEO_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
private static final int MSG_SET_PREVIEW_SURFACE = 3;
private static final int MSG_SET_DISPLAY_SURFACE = 4;
@@ -154,7 +154,7 @@
private final VideoProvider.VideoProviderHandler
mMessageHandler = new VideoProvider.VideoProviderHandler();
private final VideoProvider.VideoProviderBinder mBinder;
- private IVideoCallback mVideoListener;
+ private IVideoCallback mVideoCallback;
/**
* Default handler used to consolidate binder method calls onto a single thread.
@@ -163,8 +163,8 @@
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_SET_VIDEO_LISTENER:
- mVideoListener = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
+ case MSG_SET_VIDEO_CALLBACK:
+ mVideoCallback = IVideoCallback.Stub.asInterface((IBinder) msg.obj);
break;
case MSG_SET_CAMERA:
onSetCamera((String) msg.obj);
@@ -206,9 +206,9 @@
* IVideoProvider stub implementation.
*/
private final class VideoProviderBinder extends IVideoProvider.Stub {
- public void setVideoListener(IBinder videoListenerBinder) {
+ public void setVideoCallback(IBinder videoCallbackBinder) {
mMessageHandler.obtainMessage(
- MSG_SET_VIDEO_LISTENER, videoListenerBinder).sendToTarget();
+ MSG_SET_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
}
public void setCamera(String cameraId) {
@@ -350,9 +350,9 @@
* @param videoProfile The requested video call profile.
*/
public void receiveSessionModifyRequest(VideoProfile videoProfile) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.receiveSessionModifyRequest(videoProfile);
+ mVideoCallback.receiveSessionModifyRequest(videoProfile);
} catch (RemoteException ignored) {
}
}
@@ -370,9 +370,9 @@
*/
public void receiveSessionModifyResponse(int status,
VideoProfile requestedProfile, VideoProfile responseProfile) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.receiveSessionModifyResponse(
+ mVideoCallback.receiveSessionModifyResponse(
status, requestedProfile, responseProfile);
} catch (RemoteException ignored) {
}
@@ -390,9 +390,9 @@
* @param event The event.
*/
public void handleCallSessionEvent(int event) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.handleCallSessionEvent(event);
+ mVideoCallback.handleCallSessionEvent(event);
} catch (RemoteException ignored) {
}
}
@@ -405,9 +405,9 @@
* @param height The updated peer video height.
*/
public void changePeerDimensions(int width, int height) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changePeerDimensions(width, height);
+ mVideoCallback.changePeerDimensions(width, height);
} catch (RemoteException ignored) {
}
}
@@ -419,9 +419,9 @@
* @param dataUsage The updated data usage.
*/
public void changeCallDataUsage(int dataUsage) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changeCallDataUsage(dataUsage);
+ mVideoCallback.changeCallDataUsage(dataUsage);
} catch (RemoteException ignored) {
}
}
@@ -433,9 +433,9 @@
* @param cameraCapabilities The changed camera capabilities.
*/
public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
- if (mVideoListener != null) {
+ if (mVideoCallback != null) {
try {
- mVideoListener.changeCameraCapabilities(cameraCapabilities);
+ mVideoCallback.changeCameraCapabilities(cameraCapabilities);
} catch (RemoteException ignored) {
}
}
@@ -1068,10 +1068,10 @@
if (mState != state) {
Log.d(this, "setState: %s", stateToString(state));
mState = state;
+ onSetState(state);
for (Listener l : mListeners) {
l.onStateChanged(this, state);
}
- onSetState(state);
}
}
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 39ae59a..d5a6aa5 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -29,31 +29,25 @@
// TODO: Token to limit recursive invocations
private final PhoneAccountHandle mAccountHandle;
- private final Uri mHandle;
- private final int mHandlePresentation;
+ private final Uri mAddress;
private final Bundle mExtras;
private final int mVideoState;
/**
* @param accountHandle The accountHandle which should be used to place the call.
* @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
- * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
- * is shown.
* @param extras Application-specific extra data.
*/
public ConnectionRequest(
PhoneAccountHandle accountHandle,
Uri handle,
- int handlePresentation,
Bundle extras) {
- this(accountHandle, handle, handlePresentation, extras, VideoProfile.VideoState.AUDIO_ONLY);
+ this(accountHandle, handle, extras, VideoProfile.VideoState.AUDIO_ONLY);
}
/**
* @param accountHandle The accountHandle which should be used to place the call.
* @param handle The handle (e.g., phone number) to which the {@link Connection} is to connect.
- * @param handlePresentation The {@link PropertyPresentation} which controls how the handle
- * is shown.
* @param extras Application-specific extra data.
* @param videoState Determines the video state for the connection.
* @hide
@@ -61,20 +55,17 @@
public ConnectionRequest(
PhoneAccountHandle accountHandle,
Uri handle,
- int handlePresentation,
Bundle extras,
int videoState) {
mAccountHandle = accountHandle;
- mHandle = handle;
- mHandlePresentation = handlePresentation;
+ mAddress = handle;
mExtras = extras;
mVideoState = videoState;
}
private ConnectionRequest(Parcel in) {
mAccountHandle = in.readParcelable(getClass().getClassLoader());
- mHandle = in.readParcelable(getClass().getClassLoader());
- mHandlePresentation = in.readInt();
+ mAddress = in.readParcelable(getClass().getClassLoader());
mExtras = in.readParcelable(getClass().getClassLoader());
mVideoState = in.readInt();
}
@@ -87,12 +78,7 @@
/**
* The handle (e.g., phone number) to which the {@link Connection} is to connect.
*/
- public Uri getHandle() { return mHandle; }
-
- /**
- * The {@link PropertyPresentation} which controls how the handle is shown.
- */
- public int getHandlePresentation() { return mHandlePresentation; }
+ public Uri getAddress() { return mAddress; }
/**
* Application-specific extra data. Used for passing back information from an incoming
@@ -118,9 +104,9 @@
@Override
public String toString() {
return String.format("ConnectionRequest %s %s",
- mHandle == null
+ mAddress == null
? Uri.EMPTY
- : Connection.toLogSafePhoneNumber(mHandle.toString()),
+ : Connection.toLogSafePhoneNumber(mAddress.toString()),
mExtras == null ? "" : mExtras);
}
@@ -147,8 +133,7 @@
@Override
public void writeToParcel(Parcel destination, int flags) {
destination.writeParcelable(mAccountHandle, 0);
- destination.writeParcelable(mHandle, 0);
- destination.writeInt(mHandlePresentation);
+ destination.writeParcelable(mAddress, 0);
destination.writeParcelable(mExtras, 0);
destination.writeInt(mVideoState);
}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 2dc6910..39365b6 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -72,6 +72,8 @@
private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
private static final int MSG_ANSWER_VIDEO = 17;
+ private static final int MSG_MERGE_CONFERENCE = 18;
+ private static final int MSG_SWAP_CONFERENCE = 19;
private static Connection sNullConnection;
@@ -182,6 +184,16 @@
}
@Override
+ public void mergeConference(String callId) {
+ mHandler.obtainMessage(MSG_MERGE_CONFERENCE, callId).sendToTarget();
+ }
+
+ @Override
+ public void swapConference(String callId) {
+ mHandler.obtainMessage(MSG_SWAP_CONFERENCE, callId).sendToTarget();
+ }
+
+ @Override
public void onPostDialContinue(String callId, boolean proceed) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
@@ -298,6 +310,12 @@
case MSG_SPLIT_FROM_CONFERENCE:
splitFromConference((String) msg.obj);
break;
+ case MSG_MERGE_CONFERENCE:
+ mergeConference((String) msg.obj);
+ break;
+ case MSG_SWAP_CONFERENCE:
+ swapConference((String) msg.obj);
+ break;
case MSG_ON_POST_DIAL_CONTINUE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -639,6 +657,22 @@
}
}
+ private void mergeConference(String callId) {
+ Log.d(this, "mergeConference(%s)", callId);
+ Conference conference = findConferenceForAction(callId, "mergeConference");
+ if (conference != null) {
+ conference.onMerge();
+ }
+ }
+
+ private void swapConference(String callId) {
+ Log.d(this, "swapConference(%s)", callId);
+ Conference conference = findConferenceForAction(callId, "swapConference");
+ if (conference != null) {
+ conference.onSwap();
+ }
+ }
+
private void onPostDialContinue(String callId, boolean proceed) {
Log.d(this, "onPostDialContinue(%s)", callId);
findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
@@ -747,7 +781,7 @@
}
}
ParcelableConference parcelableConference = new ParcelableConference(
- conference.getPhoneAccount(),
+ conference.getPhoneAccountHandle(),
conference.getState(),
conference.getCapabilities(),
connectionIds);
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 80f7b57..96ea5a6 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -241,6 +241,26 @@
}
/**
+ * Instructs Telecomm to merge child calls of the specified conference call.
+ */
+ public void mergeConference(String callId) {
+ try {
+ mAdapter.mergeConference(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Instructs Telecomm to swap the child calls of the specified conference call.
+ */
+ public void swapConference(String callId) {
+ try {
+ mAdapter.swapConference(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Instructs Telecomm to turn the proximity sensor on.
*/
public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecomm/Log.java b/telecomm/java/android/telecomm/Log.java
index b8dfb11..446ae75 100644
--- a/telecomm/java/android/telecomm/Log.java
+++ b/telecomm/java/android/telecomm/Log.java
@@ -31,7 +31,7 @@
// Generic tag for all Telecomm Framework logging
private static final String TAG = "TelecommFramework";
- public static final boolean FORCE_LOGGING = true; /* STOP SHIP if true */
+ public static final boolean FORCE_LOGGING = false; /* STOP SHIP if true */
public static final boolean DEBUG = isLoggable(android.util.Log.DEBUG);
public static final boolean INFO = isLoggable(android.util.Log.INFO);
public static final boolean VERBOSE = isLoggable(android.util.Log.VERBOSE);
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 1d61a6e..d3da2ec 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -98,8 +98,8 @@
public static final String SCHEME_SIP = "sip";
private final PhoneAccountHandle mAccountHandle;
- private final Uri mHandle;
- private final String mSubscriptionNumber;
+ private final Uri mAddress;
+ private final Uri mSubscriptionAddress;
private final int mCapabilities;
private final int mIconResId;
private final CharSequence mLabel;
@@ -108,47 +108,40 @@
public static class Builder {
private PhoneAccountHandle mAccountHandle;
- private Uri mHandle;
- private String mSubscriptionNumber;
+ private Uri mAddress;
+ private Uri mSubscriptionAddress;
private int mCapabilities;
private int mIconResId;
private CharSequence mLabel;
private CharSequence mShortDescription;
private List<String> mSupportedUriSchemes = new ArrayList<String>();
- public Builder() {}
+ public Builder(PhoneAccountHandle accountHandle, CharSequence label) {
+ this.mAccountHandle = accountHandle;
+ this.mLabel = label;
+ }
- public Builder withAccountHandle(PhoneAccountHandle value) {
- this.mAccountHandle = value;
+ public Builder setAddress(Uri value) {
+ this.mAddress = value;
return this;
}
- public Builder withHandle(Uri value) {
- this.mHandle = value;
+ public Builder setSubscriptionAddress(Uri value) {
+ this.mSubscriptionAddress = value;
return this;
}
- public Builder withSubscriptionNumber(String value) {
- this.mSubscriptionNumber = value;
- return this;
- }
-
- public Builder withCapabilities(int value) {
+ public Builder setCapabilities(int value) {
this.mCapabilities = value;
return this;
}
- public Builder withIconResId(int value) {
+ public Builder setIconResId(int value) {
this.mIconResId = value;
return this;
}
- public Builder withLabel(CharSequence value) {
- this.mLabel = value;
- return this;
- }
-
- public Builder withShortDescription(CharSequence value) {
+ public Builder setShortDescription(CharSequence value) {
this.mShortDescription = value;
return this;
}
@@ -158,8 +151,9 @@
*
* @param uriScheme The URI scheme.
* @return The Builder.
+ * @hide
*/
- public Builder withSupportedUriScheme(String uriScheme) {
+ public Builder addSupportedUriScheme(String uriScheme) {
if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
this.mSupportedUriSchemes.add(uriScheme);
}
@@ -167,15 +161,17 @@
}
/**
- * Specifies additional URI schemes supported by the {@link PhoneAccount}.
+ * Specifies the URI schemes supported by the {@link PhoneAccount}.
*
* @param uriSchemes The URI schemes.
* @return The Builder.
*/
- public Builder withSupportedUriSchemes(List<String> uriSchemes) {
+ public Builder setSupportedUriSchemes(List<String> uriSchemes) {
+ mSupportedUriSchemes.clear();
+
if (uriSchemes != null && !uriSchemes.isEmpty()) {
for (String uriScheme : uriSchemes) {
- withSupportedUriScheme(uriScheme);
+ addSupportedUriScheme(uriScheme);
}
}
return this;
@@ -184,13 +180,13 @@
public PhoneAccount build() {
// If no supported URI schemes were defined, assume "tel" is supported.
if (mSupportedUriSchemes.isEmpty()) {
- withSupportedUriScheme(SCHEME_TEL);
+ addSupportedUriScheme(SCHEME_TEL);
}
return new PhoneAccount(
mAccountHandle,
- mHandle,
- mSubscriptionNumber,
+ mAddress,
+ mSubscriptionAddress,
mCapabilities,
mIconResId,
mLabel,
@@ -201,16 +197,16 @@
private PhoneAccount(
PhoneAccountHandle account,
- Uri handle,
- String subscriptionNumber,
+ Uri address,
+ Uri subscriptionAddress,
int capabilities,
int iconResId,
CharSequence label,
CharSequence shortDescription,
List<String> supportedUriSchemes) {
mAccountHandle = account;
- mHandle = handle;
- mSubscriptionNumber = subscriptionNumber;
+ mAddress = address;
+ mSubscriptionAddress = subscriptionAddress;
mCapabilities = capabilities;
mIconResId = iconResId;
mLabel = label;
@@ -218,7 +214,11 @@
mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
}
- public static Builder builder() { return new Builder(); }
+ public static Builder builder(
+ PhoneAccountHandle accountHandle,
+ CharSequence label) {
+ return new Builder(accountHandle, label);
+ }
/**
* The unique identifier of this {@code PhoneAccount}.
@@ -230,32 +230,30 @@
}
/**
- * The handle (e.g., a phone number) associated with this {@code PhoneAccount}. This
+ * The address (e.g., a phone number) associated with this {@code PhoneAccount}. This
* represents the destination from which outgoing calls using this {@code PhoneAccount}
* will appear to come, if applicable, and the destination to which incoming calls using this
* {@code PhoneAccount} may be addressed.
*
- * @return A handle expressed as a {@code Uri}, for example, a phone number.
+ * @return A address expressed as a {@code Uri}, for example, a phone number.
*/
- public Uri getHandle() {
- return mHandle;
+ public Uri getAddress() {
+ return mAddress;
}
/**
* The raw callback number used for this {@code PhoneAccount}, as distinct from
- * {@link #getHandle()}. For the majority of {@code PhoneAccount}s this should be registered
+ * {@link #getAddress()}. For the majority of {@code PhoneAccount}s this should be registered
* as {@code null}. It is used by the system for SIM-based {@code PhoneAccount} registration
* where {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(String, String)}
* or {@link android.telephony.TelephonyManager#setLine1NumberForDisplay(long, String, String)}
* has been used to alter the callback number.
* <p>
- * TODO: Should this also be a URI, for consistency? Should it be called the
- * "subscription handle"?
*
* @return The subscription number, suitable for display to the user.
*/
- public String getSubscriptionNumber() {
- return mSubscriptionNumber;
+ public Uri getSubscriptionAddress() {
+ return mSubscriptionAddress;
}
/**
@@ -295,11 +293,11 @@
}
/**
- * Determines if the {@link PhoneAccount} supports calls to/from handles with a specified URI
+ * Determines if the {@link PhoneAccount} supports calls to/from addresses with a specified URI
* scheme.
*
* @param uriScheme The URI scheme to check.
- * @return {@code True} if the {@code PhoneAccount} supports calls to/from handles with the
+ * @return {@code True} if the {@code PhoneAccount} supports calls to/from addresses with the
* specified URI scheme.
*/
public boolean supportsUriScheme(String uriScheme) {
@@ -363,8 +361,8 @@
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(mAccountHandle, 0);
- out.writeParcelable(mHandle, 0);
- out.writeString(mSubscriptionNumber);
+ out.writeParcelable(mAddress, 0);
+ out.writeParcelable(mSubscriptionAddress, 0);
out.writeInt(mCapabilities);
out.writeInt(mIconResId);
out.writeCharSequence(mLabel);
@@ -389,8 +387,8 @@
ClassLoader classLoader = PhoneAccount.class.getClassLoader();
mAccountHandle = in.readParcelable(getClass().getClassLoader());
- mHandle = in.readParcelable(getClass().getClassLoader());
- mSubscriptionNumber = in.readString();
+ mAddress = in.readParcelable(getClass().getClassLoader());
+ mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
mCapabilities = in.readInt();
mIconResId = in.readInt();
mLabel = in.readCharSequence();
diff --git a/telecomm/java/android/telecomm/PhoneCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
index 3d76608..7a338b4 100644
--- a/telecomm/java/android/telecomm/PhoneCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -27,11 +27,17 @@
/** Call supports the hold feature. */
public static final int SUPPORT_HOLD = 0x00000002;
- /** Call can currently be merged. */
- public static final int MERGE_CALLS = 0x00000004;
+ /**
+ * Calls within a conference can be merged. Some connection services create a conference call
+ * only after two calls have been merged. However, a conference call can also be added the
+ * moment there are more than one call. CDMA calls are implemented in this way because the call
+ * actions are more limited when more than one call exists. This flag allows merge to be exposed
+ * as a capability on the conference call instead of individual calls.
+ */
+ public static final int MERGE_CONFERENCE = 0x00000004;
- /** Call can currently be swapped with another call. */
- public static final int SWAP_CALLS = 0x00000008;
+ /** Calls withing a conference can be swapped between foreground and background. */
+ public static final int SWAP_CONFERENCE = 0x00000008;
/** Call currently supports adding another call to this one. */
public static final int ADD_CALL = 0x00000010;
@@ -42,8 +48,11 @@
/** Call can be muted. */
public static final int MUTE = 0x00000040;
- /** Call supports generic conference mode. */
- public static final int GENERIC_CONFERENCE = 0x00000080;
+ /**
+ * Call supports conference call management. This capability only applies to conference calls
+ * which can have other calls as children.
+ */
+ public static final int MANAGE_CONFERENCE = 0x00000080;
/**
* Local device supports video telephony.
@@ -69,8 +78,8 @@
*/
public static final int VoWIFI = 0x00000800;
- public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
- | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
+ public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE | ADD_CALL
+ | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE;
public static String toString(int capabilities) {
StringBuilder builder = new StringBuilder();
@@ -81,11 +90,11 @@
if ((capabilities & SUPPORT_HOLD) != 0) {
builder.append(" SUPPORT_HOLD");
}
- if ((capabilities & MERGE_CALLS) != 0) {
- builder.append(" MERGE_CALLS");
+ if ((capabilities & MERGE_CONFERENCE) != 0) {
+ builder.append(" MERGE_CONFERENCE");
}
- if ((capabilities & SWAP_CALLS) != 0) {
- builder.append(" SWAP_CALLS");
+ if ((capabilities & SWAP_CONFERENCE) != 0) {
+ builder.append(" SWAP_CONFERENCE");
}
if ((capabilities & ADD_CALL) != 0) {
builder.append(" ADD_CALL");
@@ -96,8 +105,8 @@
if ((capabilities & MUTE) != 0) {
builder.append(" MUTE");
}
- if ((capabilities & GENERIC_CONFERENCE) != 0) {
- builder.append(" GENERIC_CONFERENCE");
+ if ((capabilities & MANAGE_CONFERENCE) != 0) {
+ builder.append(" MANAGE_CONFERENCE");
}
if ((capabilities & SUPPORTS_VT_LOCAL) != 0) {
builder.append(" SUPPORTS_VT_LOCAL");
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
index 02f6de6..b073827 100644
--- a/telecomm/java/android/telecomm/RemoteConference.java
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -32,7 +32,7 @@
*/
public final class RemoteConference {
- public abstract static class Listener {
+ public abstract static class Callback {
public void onStateChanged(RemoteConference conference, int oldState, int newState) {}
public void onDisconnected(RemoteConference conference, int cause, String message) {}
public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}
@@ -44,7 +44,7 @@
private final String mId;
private final IConnectionService mConnectionService;
- private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
+ private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
private final List<RemoteConnection> mUnmodifiableChildConnections =
Collections.unmodifiableList(mChildConnections);
@@ -70,8 +70,8 @@
for (RemoteConnection connection : mChildConnections) {
connection.setConference(null);
}
- for (Listener l : mListeners) {
- l.onDestroyed(this);
+ for (Callback c : mCallbacks) {
+ c.onDestroyed(this);
}
}
@@ -88,8 +88,8 @@
if (mState != newState) {
int oldState = mState;
mState = newState;
- for (Listener l : mListeners) {
- l.onStateChanged(this, oldState, newState);
+ for (Callback c : mCallbacks) {
+ c.onStateChanged(this, oldState, newState);
}
}
}
@@ -99,8 +99,8 @@
if (!mChildConnections.contains(connection)) {
mChildConnections.add(connection);
connection.setConference(this);
- for (Listener l : mListeners) {
- l.onConnectionAdded(this, connection);
+ for (Callback c : mCallbacks) {
+ c.onConnectionAdded(this, connection);
}
}
}
@@ -110,8 +110,8 @@
if (mChildConnections.contains(connection)) {
mChildConnections.remove(connection);
connection.setConference(null);
- for (Listener l : mListeners) {
- l.onConnectionRemoved(this, connection);
+ for (Callback c : mCallbacks) {
+ c.onConnectionRemoved(this, connection);
}
}
}
@@ -120,8 +120,8 @@
void setCallCapabilities(int capabilities) {
if (mCallCapabilities != capabilities) {
mCallCapabilities = capabilities;
- for (Listener l : mListeners) {
- l.onCapabilitiesChanged(this, mCallCapabilities);
+ for (Callback c : mCallbacks) {
+ c.onCapabilitiesChanged(this, mCallCapabilities);
}
}
}
@@ -132,8 +132,8 @@
mDisconnectCause = cause;
mDisconnectMessage = message;
setState(Connection.STATE_DISCONNECTED);
- for (Listener l : mListeners) {
- l.onDisconnected(this, cause, message);
+ for (Callback c : mCallbacks) {
+ c.onDisconnected(this, cause, message);
}
}
}
@@ -188,11 +188,11 @@
return mDisconnectMessage;
}
- public final void addListener(Listener listener) {
- mListeners.add(listener);
+ public final void addCallback(Callback callback) {
+ mCallbacks.add(callback);
}
- public final void removeListener(Listener listener) {
- mListeners.remove(listener);
+ public final void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 31afb4b..8ad8d19 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -17,15 +17,18 @@
package android.telecomm;
import com.android.internal.telecomm.IConnectionService;
+import com.android.internal.telecomm.IVideoCallback;
+import com.android.internal.telecomm.IVideoProvider;
import android.app.PendingIntent;
import android.net.Uri;
+import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.DisconnectCause;
+import android.view.Surface;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -183,6 +186,18 @@
List<RemoteConnection> conferenceableConnections) {}
/**
+ * Indicates that the {@code VideoProvider} associated with this {@code RemoteConnection}
+ * has changed.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param videoProvider The new {@code VideoProvider} associated with this
+ * {@code RemoteConnection}.
+ * @hide
+ */
+ public void onVideoProviderChanged(
+ RemoteConnection connection, VideoProvider videoProvider) {}
+
+ /**
* Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part
* of has changed.
*
@@ -195,6 +210,185 @@
RemoteConference conference) {}
}
+ /** {@hide} */
+ public static class VideoProvider {
+
+ public abstract static class Listener {
+ public void onReceiveSessionModifyRequest(
+ VideoProvider videoProvider,
+ VideoProfile videoProfile) {}
+
+ public void onReceiveSessionModifyResponse(
+ VideoProvider videoProvider,
+ int status,
+ VideoProfile requestedProfile,
+ VideoProfile responseProfile) {}
+
+ public void onHandleCallSessionEvent(VideoProvider videoProvider, int event) {}
+
+ public void onPeerDimensionsChanged(VideoProvider videoProvider, int width, int height) {}
+
+ public void onCallDataUsageChanged(VideoProvider videoProvider, int dataUsage) {}
+
+ public void onCameraCapabilitiesChanged(
+ VideoProvider videoProvider,
+ CameraCapabilities cameraCapabilities) {}
+ }
+
+ private final IVideoCallback mVideoCallbackDelegate = new IVideoCallback() {
+ @Override
+ public void receiveSessionModifyRequest(VideoProfile videoProfile) {
+ for (Listener l : mListeners) {
+ l.onReceiveSessionModifyRequest(VideoProvider.this, videoProfile);
+ }
+ }
+
+ @Override
+ public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile,
+ VideoProfile responseProfile) {
+ for (Listener l : mListeners) {
+ l.onReceiveSessionModifyResponse(
+ VideoProvider.this,
+ status,
+ requestedProfile,
+ responseProfile);
+ }
+ }
+
+ @Override
+ public void handleCallSessionEvent(int event) {
+ for (Listener l : mListeners) {
+ l.onHandleCallSessionEvent(VideoProvider.this, event);
+ }
+ }
+
+ @Override
+ public void changePeerDimensions(int width, int height) {
+ for (Listener l : mListeners) {
+ l.onPeerDimensionsChanged(VideoProvider.this, width, height);
+ }
+ }
+
+ @Override
+ public void changeCallDataUsage(int dataUsage) {
+ for (Listener l : mListeners) {
+ l.onCallDataUsageChanged(VideoProvider.this, dataUsage);
+ }
+ }
+
+ @Override
+ public void changeCameraCapabilities(CameraCapabilities cameraCapabilities) {
+ for (Listener l : mListeners) {
+ l.onCameraCapabilitiesChanged(VideoProvider.this, cameraCapabilities);
+ }
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+ };
+
+ private final VideoCallbackServant mVideoCallbackServant =
+ new VideoCallbackServant(mVideoCallbackDelegate);
+
+ private final IVideoProvider mVideoProviderBinder;
+
+ /**
+ * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
+ * load factor before resizing, 1 means we only expect a single thread to
+ * access the map so make only a single shard
+ */
+ private final Set<Listener> mListeners = Collections.newSetFromMap(
+ new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
+
+ public VideoProvider(IVideoProvider videoProviderBinder) {
+ mVideoProviderBinder = videoProviderBinder;
+ try {
+ mVideoProviderBinder.setVideoCallback(mVideoCallbackServant.getStub().asBinder());
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void addListener(Listener l) {
+ mListeners.add(l);
+ }
+
+ public void removeListener(Listener l) {
+ mListeners.remove(l);
+ }
+
+ public void setCamera(String cameraId) {
+ try {
+ mVideoProviderBinder.setCamera(cameraId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setPreviewSurface(Surface surface) {
+ try {
+ mVideoProviderBinder.setPreviewSurface(surface);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setDisplaySurface(Surface surface) {
+ try {
+ mVideoProviderBinder.setDisplaySurface(surface);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setDeviceOrientation(int rotation) {
+ try {
+ mVideoProviderBinder.setDeviceOrientation(rotation);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setZoom(float value) {
+ try {
+ mVideoProviderBinder.setZoom(value);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void sendSessionModifyRequest(VideoProfile reqProfile) {
+ try {
+ mVideoProviderBinder.sendSessionModifyRequest(reqProfile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void sendSessionModifyResponse(VideoProfile responseProfile) {
+ try {
+ mVideoProviderBinder.sendSessionModifyResponse(responseProfile);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void requestCameraCapabilities() {
+ try {
+ mVideoProviderBinder.requestCameraCapabilities();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void requestCallDataUsage() {
+ try {
+ mVideoProviderBinder.requestCallDataUsage();
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void setPauseImage(String uri) {
+ try {
+ mVideoProviderBinder.setPauseImage(uri);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
private IConnectionService mConnectionService;
private final String mConnectionId;
/**
@@ -215,6 +409,7 @@
private boolean mConnected;
private int mCallCapabilities;
private int mVideoState;
+ private VideoProvider mVideoProvider;
private boolean mAudioModeIsVoip;
private StatusHints mStatusHints;
private Uri mHandle;
@@ -380,6 +575,14 @@
}
/**
+ * @return The video provider associated with this {@code RemoteConnection}.
+ * @hide
+ */
+ public final VideoProvider getVideoProvider() {
+ return mVideoProvider;
+ }
+
+ /**
* @return The failure code ({@see DisconnectCause}) associated with this failed
* {@code RemoteConnection}.
*/
@@ -684,6 +887,16 @@
}
}
+ /**
+ * @hide
+ */
+ void setVideoProvider(VideoProvider videoProvider) {
+ mVideoProvider = videoProvider;
+ for (Listener l : mListeners) {
+ l.onVideoProviderChanged(this, videoProvider);
+ }
+ }
+
/** @hide */
void setAudioModeIsVoip(boolean isVoip) {
mAudioModeIsVoip = isVoip;
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 0b6badb..348c36c 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -74,7 +74,7 @@
}
}
connection.setConferenceableConnections(conferenceable);
- // TODO: Do we need to support video providers for remote connections?
+ connection.setVideoState(parcel.getVideoState());
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// ... then, if it was created in a disconnected state, that indicates
// failure on the providing end, so immediately mark it destroyed
@@ -191,7 +191,7 @@
conference.setState(parcel.getState());
conference.setCallCapabilities(parcel.getCapabilities());
mConferenceById.put(callId, conference);
- conference.addListener(new RemoteConference.Listener() {
+ conference.addCallback(new RemoteConference.Callback() {
@Override
public void onDestroyed(RemoteConference c) {
mConferenceById.remove(callId);
@@ -226,7 +226,8 @@
@Override
public void setVideoProvider(String callId, IVideoProvider videoProvider) {
- // not supported for remote connections.
+ findConnectionForAction(callId, "setVideoProvider")
+ .setVideoProvider(new RemoteConnection.VideoProvider(videoProvider));
}
@Override
@@ -325,8 +326,7 @@
final String id = UUID.randomUUID().toString();
final ConnectionRequest newRequest = new ConnectionRequest(
request.getAccountHandle(),
- request.getHandle(),
- request.getHandlePresentation(),
+ request.getAddress(),
request.getExtras(),
request.getVideoState());
try {
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index f7c4f2f..ff96a5b 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -32,23 +32,24 @@
*/
public final class StatusHints implements Parcelable {
- private final ComponentName mComponentName;
+ private final ComponentName mPackageName;
private final CharSequence mLabel;
private final int mIconResId;
private final Bundle mExtras;
- public StatusHints(ComponentName componentName, CharSequence label, int iconResId, Bundle extras) {
- mComponentName = componentName;
+ public StatusHints(ComponentName packageName, CharSequence label, int iconResId,
+ Bundle extras) {
+ mPackageName = packageName;
mLabel = label;
mIconResId = iconResId;
mExtras = extras;
}
/**
- * @return A component used to load the icon.
+ * @return A package used to load the icon.
*/
- public ComponentName getComponentName() {
- return mComponentName;
+ public ComponentName getPackageName() {
+ return mPackageName;
}
/**
@@ -88,7 +89,7 @@
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeParcelable(mComponentName, flags);
+ out.writeParcelable(mPackageName, flags);
out.writeCharSequence(mLabel);
out.writeInt(mIconResId);
out.writeParcelable(mExtras, 0);
@@ -106,7 +107,7 @@
};
private StatusHints(Parcel in) {
- mComponentName = in.readParcelable(getClass().getClassLoader());
+ mPackageName = in.readParcelable(getClass().getClassLoader());
mLabel = in.readCharSequence();
mIconResId = in.readInt();
mExtras = in.readParcelable(getClass().getClassLoader());
@@ -115,16 +116,16 @@
private Drawable getIcon(Context context, int resId) {
Context packageContext;
try {
- packageContext = context.createPackageContext(mComponentName.getPackageName(), 0);
+ packageContext = context.createPackageContext(mPackageName.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
- Log.e(this, e, "Cannot find package %s", mComponentName.getPackageName());
+ Log.e(this, e, "Cannot find package %s", mPackageName.getPackageName());
return null;
}
try {
return packageContext.getDrawable(resId);
} catch (MissingResourceException e) {
Log.e(this, e, "Cannot find icon %d in package %s",
- resId, mComponentName.getPackageName());
+ resId, mPackageName.getPackageName());
return null;
}
}
@@ -133,7 +134,7 @@
public boolean equals(Object other) {
if (other != null && other instanceof StatusHints) {
StatusHints otherHints = (StatusHints) other;
- return Objects.equals(otherHints.getComponentName(), getComponentName()) &&
+ return Objects.equals(otherHints.getPackageName(), getPackageName()) &&
Objects.equals(otherHints.getLabel(), getLabel()) &&
otherHints.getIconResId() == getIconResId() &&
Objects.equals(otherHints.getExtras(), getExtras());
@@ -143,7 +144,7 @@
@Override
public int hashCode() {
- return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconResId +
+ return Objects.hashCode(mPackageName) + Objects.hashCode(mLabel) + mIconResId +
Objects.hashCode(mExtras);
}
}
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 071b719..5e9e6d0 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -46,27 +46,34 @@
*
* @hide
*/
- public static final String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
+ public static final String ACTION_INCOMING_CALL = "android.telecomm.action.INCOMING_CALL";
/**
* The {@link android.content.Intent} action used to configure a
* {@link android.telecomm.ConnectionService}.
*/
public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
- "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
+ "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
/**
* The {@link android.content.Intent} action used to show the call settings page.
*/
public static final String ACTION_SHOW_CALL_SETTINGS =
- "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+ "android.telecomm.action.SHOW_CALL_SETTINGS";
+
+ /**
+ * The {@link android.content.Intent} action used to show the settings page used to configure
+ * {@link PhoneAccount} preferences.
+ */
+ public static final String ACTION_CHANGE_PHONE_ACCOUNTS =
+ "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
* determines whether the speakerphone should be automatically turned on for an outgoing call.
*/
public static final String EXTRA_START_CALL_WITH_SPEAKERPHONE =
- "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+ "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} containing an integer that
@@ -79,7 +86,7 @@
* @hide
*/
public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
- "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
+ "android.telecomm.extra.START_CALL_WITH_VIDEO_STATE";
/**
* The extra used with an {@link android.content.Intent#ACTION_CALL} and
@@ -89,7 +96,7 @@
* Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
*/
public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
- "android.intent.extra.PHONE_ACCOUNT_HANDLE";
+ "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
/**
* Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
@@ -99,7 +106,7 @@
* @hide
*/
public static final String EXTRA_INCOMING_CALL_EXTRAS =
- "android.intent.extra.INCOMING_CALL_EXTRAS";
+ "android.telecomm.extra.INCOMING_CALL_EXTRAS";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} and
@@ -110,7 +117,7 @@
* @hide
*/
public static final String EXTRA_OUTGOING_CALL_EXTRAS =
- "android.intent.extra.OUTGOING_CALL_EXTRAS";
+ "android.telecomm.extra.OUTGOING_CALL_EXTRAS";
/**
* Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
@@ -196,7 +203,7 @@
* @hide
*/
public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
- "android.telecomm.intent.action.CURRENT_TTY_MODE_CHANGED";
+ "android.telecomm.action.CURRENT_TTY_MODE_CHANGED";
/**
* The lookup key for an int that indicates the current TTY mode.
@@ -219,7 +226,7 @@
* @hide
*/
public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
- "android.telecomm.intent.action.TTY_PREFERRED_MODE_CHANGED";
+ "android.telecomm.action.TTY_PREFERRED_MODE_CHANGED";
/**
* The lookup key for an int that indicates preferred TTY mode. Valid modes are: -
@@ -287,16 +294,38 @@
}
/**
+ * Return the {@link PhoneAccount} which is the user-chosen default for making outgoing phone
+ * calls. This {@code PhoneAccount} will always be a member of the list which is returned from
+ * calling {@link #getEnabledPhoneAccounts()}
+ *
+ * Apps must be prepared for this method to return {@code null}, indicating that there currently
+ * exists no user-chosen default {@code PhoneAccount}.
+ *
+ * @return The user outgoing phone account selected by the user.
+ * @hide
+ */
+ public PhoneAccountHandle getUserSelectedOutgoingPhoneAccount() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getUserSelectedOutgoingPhoneAccount();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getUserSelectedOutgoingPhoneAccount", e);
+ }
+ return null;
+ }
+
+ /**
* Sets the default account for making outgoing phone calls.
* @hide
*/
- public void setDefaultOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
+ public void setUserSelectedOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
try {
if (isServiceConnected()) {
- getTelecommService().setDefaultOutgoingPhoneAccount(accountHandle);
+ getTelecommService().setUserSelectedOutgoingPhoneAccount(accountHandle);
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecommService#setDefaultOutgoingPhoneAccount");
+ Log.e(TAG, "Error calling ITelecommService#setUserSelectedOutgoingPhoneAccount");
}
}
@@ -368,6 +397,17 @@
}
/**
+ * Returns the current connection manager. Apps must be prepared for this method to return
+ * {@code null}, indicating that there currently exists no user-chosen default
+ * {@code PhoneAccount}.
+ *
+ * @return The phone account handle of the current connection manager.
+ */
+ public PhoneAccountHandle getConnectionManager() {
+ return getSimCallManager();
+ }
+
+ /**
* Returns a list of {@link PhoneAccountHandle}s which can be used to make and receive phone
* calls which support the specified URI scheme.
* <P>
@@ -702,4 +742,4 @@
}
return isConnected;
}
-}
\ No newline at end of file
+}
diff --git a/telecomm/java/android/telecomm/VideoCallImpl.java b/telecomm/java/android/telecomm/VideoCallImpl.java
index c10865f..d33a351 100644
--- a/telecomm/java/android/telecomm/VideoCallImpl.java
+++ b/telecomm/java/android/telecomm/VideoCallImpl.java
@@ -157,7 +157,7 @@
mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
mBinder = new VideoCallListenerBinder();
- mVideoProvider.setVideoListener(mBinder);
+ mVideoProvider.setVideoCallback(mBinder);
}
/** {@inheritDoc} */
diff --git a/telecomm/java/android/telecomm/VideoCallbackServant.java b/telecomm/java/android/telecomm/VideoCallbackServant.java
new file mode 100644
index 0000000..060b8a9
--- /dev/null
+++ b/telecomm/java/android/telecomm/VideoCallbackServant.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 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
+ R* limitations under the License.
+ */
+
+package android.telecomm;
+
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telecomm.IVideoCallback;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+
+/**
+ * A component that provides an RPC servant implementation of {@link IVideoCallback},
+ * posting incoming messages on the main thread on a client-supplied delegate object.
+ *
+ * TODO: Generate this and similar classes using a compiler starting from AIDL interfaces.
+ *
+ * @hide
+ */
+final class VideoCallbackServant {
+ private static final int MSG_RECEIVE_SESSION_MODIFY_REQUEST = 0;
+ private static final int MSG_RECEIVE_SESSION_MODIFY_RESPONSE = 1;
+ private static final int MSG_HANDLE_CALL_SESSION_EVENT = 2;
+ private static final int MSG_CHANGE_PEER_DIMENSIONS = 3;
+ private static final int MSG_CHANGE_CALL_DATA_USAGE = 4;
+ private static final int MSG_CHANGE_CAMERA_CAPABILITIES = 5;
+
+ private final IVideoCallback mDelegate;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ try {
+ internalHandleMessage(msg);
+ } catch (RemoteException e) {
+ }
+ }
+
+ // Internal method defined to centralize handling of RemoteException
+ private void internalHandleMessage(Message msg) throws RemoteException {
+ switch (msg.what) {
+ case MSG_RECEIVE_SESSION_MODIFY_REQUEST: {
+ mDelegate.receiveSessionModifyRequest((VideoProfile) msg.obj);
+ break;
+ }
+ case MSG_RECEIVE_SESSION_MODIFY_RESPONSE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.receiveSessionModifyResponse(
+ args.argi1,
+ (VideoProfile) args.arg1,
+ (VideoProfile) args.arg2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_HANDLE_CALL_SESSION_EVENT: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.handleCallSessionEvent(args.argi1);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_PEER_DIMENSIONS: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.changePeerDimensions(args.argi1, args.argi2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_CALL_DATA_USAGE: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.changeCallDataUsage(args.argi1);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_CHANGE_CAMERA_CAPABILITIES: {
+ mDelegate.changeCameraCapabilities((CameraCapabilities) msg.obj);
+ break;
+ }
+ }
+ }
+ };
+
+ private final IVideoCallback mStub = new IVideoCallback.Stub() {
+ @Override
+ public void receiveSessionModifyRequest(VideoProfile videoProfile) throws RemoteException {
+ mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST, videoProfile).sendToTarget();
+ }
+
+ @Override
+ public void receiveSessionModifyResponse(int status, VideoProfile requestedProfile,
+ VideoProfile responseProfile) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = status;
+ args.arg1 = requestedProfile;
+ args.arg2 = responseProfile;
+ mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_RESPONSE, args).sendToTarget();
+ }
+
+ @Override
+ public void handleCallSessionEvent(int event) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = event;
+ mHandler.obtainMessage(MSG_HANDLE_CALL_SESSION_EVENT, args).sendToTarget();
+ }
+
+ @Override
+ public void changePeerDimensions(int width, int height) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = width;
+ args.argi2 = height;
+ mHandler.obtainMessage(MSG_CHANGE_PEER_DIMENSIONS, args).sendToTarget();
+ }
+
+ @Override
+ public void changeCallDataUsage(int dataUsage) throws RemoteException {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = dataUsage;
+ mHandler.obtainMessage(MSG_CHANGE_CALL_DATA_USAGE, args).sendToTarget();
+ }
+
+ @Override
+ public void changeCameraCapabilities(CameraCapabilities cameraCapabilities)
+ throws RemoteException {
+ mHandler.obtainMessage(MSG_CHANGE_CAMERA_CAPABILITIES, cameraCapabilities)
+ .sendToTarget();
+ }
+ };
+
+ public VideoCallbackServant(IVideoCallback delegate) {
+ mDelegate = delegate;
+ }
+
+ public IVideoCallback getStub() {
+ return mStub;
+ }
+}
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 32b877d..a673733 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -65,6 +65,10 @@
void splitFromConference(String callId);
+ void mergeConference(String conferenceCallId);
+
+ void swapConference(String conferenceCallId);
+
void onPostDialContinue(String callId, boolean proceed);
void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 2ce5c6b..626bb91 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -54,6 +54,10 @@
void splitFromConference(String callId);
+ void mergeConference(String callId);
+
+ void swapConference(String callId);
+
void turnOnProximitySensor();
void turnOffProximitySensor(boolean screenOnImmediately);
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index a6ab3ac..6ab78c4 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -40,9 +40,14 @@
PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme);
/**
- * @see TelecommServiceImpl#setDefaultOutgoingPhoneAccount
+ * @see TelecommServiceImpl#getUserSelectedOutgoingPhoneAccount
*/
- void setDefaultOutgoingPhoneAccount(in PhoneAccountHandle account);
+ PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
+
+ /**
+ * @see TelecommServiceImpl#setUserSelectedOutgoingPhoneAccount
+ */
+ void setUserSelectedOutgoingPhoneAccount(in PhoneAccountHandle account);
/**
* @see TelecommServiceImpl#getOutgoingPhoneAccounts
diff --git a/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
index 9d3ad7f..b0aa988 100644
--- a/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IVideoProvider.aidl
@@ -25,7 +25,7 @@
* @hide
*/
oneway interface IVideoProvider {
- void setVideoListener(IBinder videoListenerBinder);
+ void setVideoCallback(IBinder videoCallbackBinder);
void setCamera(String cameraId);
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
index dbe38ea..4621f91 100644
--- a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
@@ -27,7 +27,7 @@
/**
* Indicates an invalid channel.
*/
- public static int INVALID_CHANNEL = -1;
+ public static final int INVALID_CHANNEL = -1;
/**
* Possible status values returned by open channel command.
@@ -37,10 +37,10 @@
* STATUS_NO_SUCH_ELEMENT: AID not found on UICC.
* STATUS_UNKNOWN_ERROR: Unknown error in open channel command.
*/
- public static int STATUS_NO_ERROR = 1;
- public static int STATUS_MISSING_RESOURCE = 2;
- public static int STATUS_NO_SUCH_ELEMENT = 3;
- public static int STATUS_UNKNOWN_ERROR = 4;
+ public static final int STATUS_NO_ERROR = 1;
+ public static final int STATUS_MISSING_RESOURCE = 2;
+ public static final int STATUS_NO_SUCH_ELEMENT = 3;
+ public static final int STATUS_UNKNOWN_ERROR = 4;
private final int mChannel;
private final int mStatus;
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index acb97a0..30799f8 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -38,8 +38,8 @@
import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
import java.util.Locale;
import java.util.regex.Matcher;
@@ -164,14 +164,6 @@
return uri.getSchemeSpecificPart();
}
- // TODO: We don't check for SecurityException here (requires
- // CALL_PRIVILEGED permission).
- if (scheme.equals("voicemail")) {
- long subId = intent.getLongExtra(SUBSCRIPTION_KEY,
- SubscriptionManager.getDefaultVoiceSubId());
- return TelephonyManager.getDefault().getCompleteVoiceMailNumber(subId);
- }
-
if (context == null) {
return null;
}
@@ -2223,81 +2215,79 @@
cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormat) {
String retStr = dialStr;
+ boolean useNanp = (currFormat == defaultFormat) && (currFormat == FORMAT_NANP);
+
// Checks if the plus sign character is in the passed-in dial string
if (dialStr != null &&
dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) {
- // Format the string based on the rules for the country the number is from,
- // and the current country the phone is camped on.
- if ((currFormat == defaultFormat) && (currFormat == FORMAT_NANP)) {
- // Handle case where default and current telephone numbering plans are NANP.
- String postDialStr = null;
- String tempDialStr = dialStr;
- // Sets the retStr to null since the conversion will be performed below.
- retStr = null;
- if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
- // This routine is to process the plus sign in the dial string by loop through
- // the network portion, post dial portion 1, post dial portion 2... etc. if
- // applied
- do {
- String networkDialStr;
+ // Handle case where default and current telephone numbering plans are NANP.
+ String postDialStr = null;
+ String tempDialStr = dialStr;
+
+ // Sets the retStr to null since the conversion will be performed below.
+ retStr = null;
+ if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
+ // This routine is to process the plus sign in the dial string by loop through
+ // the network portion, post dial portion 1, post dial portion 2... etc. if
+ // applied
+ do {
+ String networkDialStr;
+ // Format the string based on the rules for the country the number is from,
+ // and the current country the phone is camped
+ if (useNanp) {
networkDialStr = extractNetworkPortion(tempDialStr);
- // Handles the conversion within NANP
- networkDialStr = processPlusCodeWithinNanp(networkDialStr);
+ } else {
+ networkDialStr = extractNetworkPortionAlt(tempDialStr);
- // Concatenates the string that is converted from network portion
- if (!TextUtils.isEmpty(networkDialStr)) {
- if (retStr == null) {
- retStr = networkDialStr;
- } else {
- retStr = retStr.concat(networkDialStr);
- }
+ }
+
+ networkDialStr = processPlusCode(networkDialStr, useNanp);
+
+ // Concatenates the string that is converted from network portion
+ if (!TextUtils.isEmpty(networkDialStr)) {
+ if (retStr == null) {
+ retStr = networkDialStr;
} else {
- // This should never happen since we checked the if dialStr is null
- // and if it contains the plus sign in the beginning of this function.
- // The plus sign is part of the network portion.
- Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
- return dialStr;
+ retStr = retStr.concat(networkDialStr);
}
- postDialStr = extractPostDialPortion(tempDialStr);
- if (!TextUtils.isEmpty(postDialStr)) {
- int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
+ } else {
+ // This should never happen since we checked the if dialStr is null
+ // and if it contains the plus sign in the beginning of this function.
+ // The plus sign is part of the network portion.
+ Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
+ return dialStr;
+ }
+ postDialStr = extractPostDialPortion(tempDialStr);
+ if (!TextUtils.isEmpty(postDialStr)) {
+ int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
- // dialableIndex should always be greater than 0
- if (dialableIndex >= 1) {
- retStr = appendPwCharBackToOrigDialStr(dialableIndex,
- retStr,postDialStr);
- // Skips the P/W character, extracts the dialable portion
- tempDialStr = postDialStr.substring(dialableIndex);
- } else {
- // Non-dialable character such as P/W should not be at the end of
- // the dial string after P/W processing in CdmaConnection.java
- // Set the postDialStr to "" to break out of the loop
- if (dialableIndex < 0) {
- postDialStr = "";
- }
- Rlog.e("wrong postDialStr=", postDialStr);
+ // dialableIndex should always be greater than 0
+ if (dialableIndex >= 1) {
+ retStr = appendPwCharBackToOrigDialStr(dialableIndex,
+ retStr,postDialStr);
+ // Skips the P/W character, extracts the dialable portion
+ tempDialStr = postDialStr.substring(dialableIndex);
+ } else {
+ // Non-dialable character such as P/W should not be at the end of
+ // the dial string after P/W processing in CdmaConnection.java
+ // Set the postDialStr to "" to break out of the loop
+ if (dialableIndex < 0) {
+ postDialStr = "";
}
+ Rlog.e("wrong postDialStr=", postDialStr);
}
- if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
- } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
- } else {
- // TODO: Support NANP international conversion and other telephone numbering plans.
- // Currently the phone is never used in non-NANP system, so return the original
- // dial string.
- Rlog.e("checkAndProcessPlusCode:non-NANP not supported", dialStr);
- }
+ }
+ if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
+ } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
}
return retStr;
- }
+ }
- // This function gets the default international dialing prefix
- private static String getDefaultIdp( ) {
- String ps = null;
- SystemProperties.get(PROPERTY_IDP_STRING, ps);
- if (TextUtils.isEmpty(ps)) {
- ps = NANP_IDP_STRING;
- }
+ private static String getCurrentIdp(boolean useNanp) {
+ // in case, there is no IDD is found, we shouldn't convert it.
+ String ps = SystemProperties.get(
+ PROPERTY_OPERATOR_IDP_STRING, useNanp ? NANP_IDP_STRING : PLUS_SIGN_STRING);
return ps;
}
@@ -2326,8 +2316,9 @@
/**
* This function checks if the passed in string conforms to the NANP format
* i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
+ * @hide
*/
- private static boolean isNanp (String dialStr) {
+ public static boolean isNanp (String dialStr) {
boolean retVal = false;
if (dialStr != null) {
if (dialStr.length() == NANP_LENGTH) {
@@ -2407,31 +2398,32 @@
}
/**
- * This function handles the plus code conversion within NANP CDMA network
+ * This function handles the plus code conversion
* If the number format is
* 1)+1NANP,remove +,
* 2)other than +1NANP, any + numbers,replace + with the current IDP
*/
- private static String processPlusCodeWithinNanp(String networkDialStr) {
+ private static String processPlusCode(String networkDialStr, boolean useNanp) {
String retStr = networkDialStr;
- if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
+ if (DBG) log("processPlusCode, networkDialStr = " + networkDialStr
+ + "for NANP = " + useNanp);
// If there is a plus sign at the beginning of the dial string,
// Convert the plus sign to the default IDP since it's an international number
if (networkDialStr != null &&
networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
networkDialStr.length() > 1) {
String newStr = networkDialStr.substring(1);
- if (isOneNanp(newStr)) {
+ // TODO: for nonNanp, should the '+' be removed if following number is country code
+ if (useNanp && isOneNanp(newStr)) {
// Remove the leading plus sign
retStr = newStr;
- } else {
- String idpStr = getDefaultIdp();
- // Replaces the plus sign with the default IDP
- retStr = networkDialStr.replaceFirst("[+]", idpStr);
+ } else {
+ // Replaces the plus sign with the default IDP
+ retStr = networkDialStr.replaceFirst("[+]", getCurrentIdp(useNanp));
}
}
- if (DBG) log("processPlusCodeWithinNanp,retStr=" + retStr);
+ if (DBG) log("processPlusCode, retStr=" + retStr);
return retStr;
}
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index 55781fa..805f787 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2011-2014 MediaTek Inc.
-*
-* 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.
-*/
+ * Copyright (C) 2014 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.telephony;
@@ -20,95 +20,148 @@
import android.os.Parcelable;
/**
- * A parcelable holder class of byte[] for ISms aidl implementation
- * @hide
+ * A Parcelable class for Subscription Information.
+ * @hide - to be unhidden
*/
-
public class SubInfoRecord implements Parcelable {
- public long mSubId;
- public String mIccId;
- public int mSlotId;
- public String mDisplayName;
- public int mNameSource;
- public int mColor;
- public String mNumber;
- public int mDisplayNumberFormat;
- public int mDataRoaming;
- public int[] mSimIconRes;
+ /**
+ * Subscription Identifier, this is a device unique number
+ * and not an index into an array
+ */
+ public long subId;
+ /** The GID for a SIM that maybe associated with this subscription, empty if unknown */
+ public String iccId;
+ /**
+ * The slot identifier for that currently contains the subscription
+ * and not necessarily unique and maybe INVALID_SLOT_ID if unknown
+ */
+ public int slotId;
+ /**
+ * The string displayed to the user that identifies this subscription
+ */
+ public String displayName;
+ /**
+ * The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
+ * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
+ */
+ public int nameSource;
+ /**
+ * The color to be used for when displaying to the user
+ */
+ public int color;
+ /**
+ * A number presented to the user identify this subscription
+ */
+ public String number;
+ /**
+ * How to display the phone number, DISPLAY_NUMBER_NONE, DISPLAY_NUMBER_FIRST,
+ * DISPLAY_NUMBER_LAST
+ */
+ public int displayNumberFormat;
+ /**
+ * Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
+ */
+ public int dataRoaming;
+ /**
+ * SIM Icon resource identifiers. FIXME: Check with MTK what it really is
+ */
+ public int[] simIconRes;
+ /**
+ * Mobile Country Code
+ */
+ public int mcc;
+ /**
+ * Mobile Network Code
+ */
+ public int mnc;
public SubInfoRecord() {
- this.mSubId = SubscriptionManager.INVALID_SUB_ID;
- this.mIccId = "";
- this.mSlotId = SubscriptionManager.INVALID_SLOT_ID;
- this.mDisplayName = "";
- this.mNameSource = 0;
- this.mColor = 0;
- this.mNumber = "";
- this.mDisplayNumberFormat = 0;
- this.mDataRoaming = 0;
- this.mSimIconRes = new int[2];
+ this.subId = SubscriptionManager.INVALID_SUB_ID;
+ this.iccId = "";
+ this.slotId = SubscriptionManager.INVALID_SLOT_ID;
+ this.displayName = "";
+ this.nameSource = 0;
+ this.color = 0;
+ this.number = "";
+ this.displayNumberFormat = 0;
+ this.dataRoaming = 0;
+ this.simIconRes = new int[2];
+ this.mcc = 0;
+ this.mnc = 0;
}
- public SubInfoRecord(long subId, String iccId, int slotId, String displayName,
- int nameSource, int mColor, String mNumber, int displayFormat, int roaming, int[] iconRes) {
- this.mSubId = subId;
- this.mIccId = iccId;
- this.mSlotId = slotId;
- this.mDisplayName = displayName;
- this.mNameSource = nameSource;
- this.mColor = mColor;
- this.mNumber = mNumber;
- this.mDisplayNumberFormat = displayFormat;
- this.mDataRoaming = roaming;
- this.mSimIconRes = iconRes;
+ public SubInfoRecord(long subId, String iccId, int slotId, String displayName, int nameSource,
+ int color, String number, int displayFormat, int roaming, int[] iconRes,
+ int mcc, int mnc) {
+ this.subId = subId;
+ this.iccId = iccId;
+ this.slotId = slotId;
+ this.displayName = displayName;
+ this.nameSource = nameSource;
+ this.color = color;
+ this.number = number;
+ this.displayNumberFormat = displayFormat;
+ this.dataRoaming = roaming;
+ this.simIconRes = iconRes;
+ this.mcc = mcc;
+ this.mnc = mnc;
}
public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() {
+ @Override
public SubInfoRecord createFromParcel(Parcel source) {
- long mSubId = source.readLong();
- String mIccId = source.readString();
- int mSlotId = source.readInt();
- String mDisplayName = source.readString();
- int mNameSource = source.readInt();
- int mColor = source.readInt();
- String mNumber = source.readString();
- int mDisplayNumberFormat = source.readInt();
- int mDataRoaming = source.readInt();
+ long subId = source.readLong();
+ String iccId = source.readString();
+ int slotId = source.readInt();
+ String displayName = source.readString();
+ int nameSource = source.readInt();
+ int color = source.readInt();
+ String number = source.readString();
+ int displayNumberFormat = source.readInt();
+ int dataRoaming = source.readInt();
int[] iconRes = new int[2];
source.readIntArray(iconRes);
+ int mcc = source.readInt();
+ int mnc = source.readInt();
- return new SubInfoRecord(mSubId, mIccId, mSlotId, mDisplayName, mNameSource, mColor, mNumber,
- mDisplayNumberFormat, mDataRoaming, iconRes);
+ return new SubInfoRecord(subId, iccId, slotId, displayName, nameSource, color, number,
+ displayNumberFormat, dataRoaming, iconRes, mcc, mnc);
}
+ @Override
public SubInfoRecord[] newArray(int size) {
return new SubInfoRecord[size];
}
};
+ @Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mSubId);
- dest.writeString(mIccId);
- dest.writeInt(mSlotId);
- dest.writeString(mDisplayName);
- dest.writeInt(mNameSource);
- dest.writeInt(mColor);
- dest.writeString(mNumber);
- dest.writeInt(mDisplayNumberFormat);
- dest.writeInt(mDataRoaming);
- dest.writeIntArray(mSimIconRes);
+ dest.writeLong(subId);
+ dest.writeString(iccId);
+ dest.writeInt(slotId);
+ dest.writeString(displayName);
+ dest.writeInt(nameSource);
+ dest.writeInt(color);
+ dest.writeString(number);
+ dest.writeInt(displayNumberFormat);
+ dest.writeInt(dataRoaming);
+ dest.writeIntArray(simIconRes);
+ dest.writeInt(mcc);
+ dest.writeInt(mnc);
}
+ @Override
public int describeContents() {
return 0;
}
+ @Override
public String toString() {
- return "{mSubId=" + mSubId + ", mIccId=" + mIccId + " mSlotId=" + mSlotId
- + " mDisplayName=" + mDisplayName + " mNameSource=" + mNameSource
- + " mColor=" + mColor + " mNumber=" + mNumber
- + " mDisplayNumberFormat=" + mDisplayNumberFormat + " mDataRoaming=" + mDataRoaming
- + " mSimIconRes=" + mSimIconRes + "}";
+ return "{mSubId=" + subId + ", mIccId=" + iccId + " mSlotId=" + slotId
+ + " mDisplayName=" + displayName + " mNameSource=" + nameSource
+ + " mColor=" + color + " mNumber=" + number
+ + " mDisplayNumberFormat=" + displayNumberFormat + " mDataRoaming=" + dataRoaming
+ + " mSimIconRes=" + simIconRes + " mMcc " + mcc + " mMnc " + mnc + "}";
}
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 2bb2404..d0f355e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -27,45 +27,49 @@
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.PhoneConstants;
+
+import java.util.ArrayList;
import java.util.List;
/**
* SubscriptionManager is the application interface to SubscriptionController
* and provides information about the current Telephony Subscriptions.
*
- * @hide
+ * The android.Manifest.permission.READ_PHONE_STATE to retrieve the information, except
+ * getActiveSubIdList and getActiveSubIdCount for which no permission is needed.
+ *
+ * @hide - to be unhidden
*/
public class SubscriptionManager implements BaseColumns {
private static final String LOG_TAG = "SUB";
private static final boolean DBG = true;
private static final boolean VDBG = false;
- // An invalid phone identifier
- /** @hide */
+ /** An invalid phone identifier */
+ /** @hide - to be unhidden */
public static final int INVALID_PHONE_ID = -1000;
- // Indicates the caller wants the default phone id.
- /** @hide */
+ /** Indicates the caller wants the default phone id. */
+ /** @hide - to be unhidden */
public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE;
- // An invalid slot identifier
- /** @hide */
+ /** An invalid slot identifier */
+ /** @hide - to be unhidden */
public static final int INVALID_SLOT_ID = -1000;
- // Indicates the caller wants the default slot id.
+ /** Indicates the caller wants the default slot id. */
/** @hide */
public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE;
- // An invalid subscription identifier
- /** @hide */
- public static final long INVALID_SUB_ID = -1000;
-
- // Indicates the user should be asked which sub to use.
+ /** Indicates the user should be asked which sub to use. */
/** @hide */
public static final long ASK_USER_SUB_ID = -1001;
- // Indicates the caller wants the default sub id.
- /** @hide */
+ /** An invalid subscription identifier */
+ public static final long INVALID_SUB_ID = -1000;
+
+ /** Indicates the caller wants the default sub id. */
+ /** @hide - to be unhidden */
public static final long DEFAULT_SUB_ID = Long.MAX_VALUE;
/** @hide */
@@ -108,40 +112,58 @@
*/
/** @hide */
public static final String SIM_ID = "sim_id";
- /** @hide */
+
+ /** SIM is not inserted */
+ /** @hide - to be unhidden */
public static final int SIM_NOT_INSERTED = -1;
/**
- * The display name of a SIM.
+ * TelephonyProvider column name for user displayed name.
* <P>Type: TEXT (String)</P>
*/
/** @hide */
public static final String DISPLAY_NAME = "display_name";
- /** @hide */
+ /**
+ * Default name resource
+ * @hide
+ */
public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName;
/**
- * The display name source of a SIM.
- * <P>Type: INT (int)</P>
+ * TelephonyProvider column name for source of the user displayed name.
+ * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
+ *
+ * @hide
*/
- /** @hide */
public static final String NAME_SOURCE = "name_source";
- /** @hide */
+ /**
+ * The name_source is undefined
+ * @hide
+ */
public static final int NAME_SOURCE_UNDEFINDED = -1;
- /** @hide */
+ /**
+ * The name_source is the default
+ * @hide
+ */
public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
- /** @hide */
+ /**
+ * The name_source is from the SIM
+ * @hide
+ */
public static final int NAME_SOURCE_SIM_SOURCE = 1;
- /** @hide */
+ /**
+ * The name_source is from the user
+ * @hide
+ */
public static final int NAME_SOURCE_USER_INPUT = 2;
/**
- * The color of a SIM.
+ * TelephonyProvider column name for the color of a SIM.
* <P>Type: INTEGER (int)</P>
*/
/** @hide */
@@ -163,14 +185,14 @@
public static final int COLOR_DEFAULT = COLOR_1;
/**
- * The phone number of a SIM.
+ * TelephonyProvider column name for the phone number of a SIM.
* <P>Type: TEXT (String)</P>
*/
/** @hide */
public static final String NUMBER = "number";
/**
- * The number display format of a SIM.
+ * TelephonyProvider column name for the number display format of a SIM.
* <P>Type: INTEGER (int)</P>
*/
/** @hide */
@@ -189,7 +211,7 @@
public static final int DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
/**
- * Permission for data roaming of a SIM.
+ * TelephonyProvider column name for permission for data roaming of a SIM.
* <P>Type: INTEGER (int)</P>
*/
/** @hide */
@@ -204,6 +226,19 @@
/** @hide */
public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
+ /**
+ * TelephonyProvider column name for the MCC associated with a SIM.
+ * <P>Type: INTEGER (int)</P>
+ */
+ public static final String MCC = "mcc";
+
+ /**
+ * TelephonyProvider column name for the MNC associated with a SIM.
+ * <P>Type: INTEGER (int)</P>
+ */
+ public static final String MNC = "mnc";
+
+
private static final int RES_TYPE_BACKGROUND_DARK = 0;
private static final int RES_TYPE_BACKGROUND_LIGHT = 1;
@@ -225,14 +260,14 @@
}
/**
- * Get the SubInfoRecord according to an index
+ * Get the SubInfoRecord associated with the subId
* @param subId The unique SubInfoRecord index in database
* @return SubInfoRecord, maybe null
- * @hide
+ * @hide - to be unhidden
*/
- public static SubInfoRecord getSubInfoUsingSubId(long subId) {
+ public static SubInfoRecord getSubInfoForSubscriber(long subId) {
if (!isValidSubId(subId)) {
- logd("[getSubInfoUsingSubIdx]- invalid subId");
+ logd("[getSubInfoForSubscriberx]- invalid subId");
return null;
}
@@ -241,7 +276,7 @@
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subInfo = iSub.getSubInfoUsingSubId(subId);
+ subInfo = iSub.getSubInfoForSubscriber(subId);
}
} catch (RemoteException ex) {
// ignore it
@@ -254,7 +289,7 @@
/**
* Get the SubInfoRecord according to an IccId
* @param iccId the IccId of SIM card
- * @return SubInfoRecord, maybe null
+ * @return SubInfoRecord List, maybe empty but not null
* @hide
*/
public static List<SubInfoRecord> getSubInfoUsingIccId(String iccId) {
@@ -275,14 +310,18 @@
// ignore it
}
+
+ if (result == null) {
+ result = new ArrayList<SubInfoRecord>();
+ }
return result;
}
/**
* Get the SubInfoRecord according to slotId
* @param slotId the slot which the SIM is inserted
- * @return SubInfoRecord, maybe null
- * @hide
+ * @return SubInfoRecord list, maybe empty but not null
+ * @hide - to be unhidden
*/
public static List<SubInfoRecord> getSubInfoUsingSlotId(int slotId) {
// FIXME: Consider never returning null
@@ -302,12 +341,17 @@
// ignore it
}
+
+ if (result == null) {
+ result = new ArrayList<SubInfoRecord>();
+ }
return result;
}
/**
- * Get all the SubInfoRecord(s) in subinfo database
- * @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
+ * Get all the SubInfoRecord(s) in subInfo database
+ * @return List of all SubInfoRecords in database, include those that were inserted before
+ * maybe empty but not null.
* @hide
*/
public static List<SubInfoRecord> getAllSubInfoList() {
@@ -324,13 +368,16 @@
// ignore it
}
+ if (result == null) {
+ result = new ArrayList<SubInfoRecord>();
+ }
return result;
}
/**
* Get the SubInfoRecord(s) of the currently inserted SIM(s)
- * @return Array list of currently inserted SubInfoRecord(s)
- * @hide
+ * @return Array list of currently inserted SubInfoRecord(s) maybe empty but not null
+ * @hide - to be unhidden
*/
public static List<SubInfoRecord> getActiveSubInfoList() {
List<SubInfoRecord> result = null;
@@ -344,6 +391,9 @@
// ignore it
}
+ if (result == null) {
+ result = new ArrayList<SubInfoRecord>();
+ }
return result;
}
@@ -580,7 +630,12 @@
return result;
}
- /** @hide */
+ /**
+ * Get slotId associated with the subscription.
+ * @return slotId as a positive integer or a negative value if an error either
+ * SIM_NOT_INSERTED or INVALID_SLOT_ID.
+ * @hide - to be unhidden
+ */
public static int getSlotId(long subId) {
if (!isValidSubId(subId)) {
logd("[getSlotId]- fail");
@@ -728,7 +783,7 @@
/** @hide */
public static SubInfoRecord getDefaultVoiceSubInfo() {
- return getSubInfoUsingSubId(getDefaultVoiceSubId());
+ return getSubInfoForSubscriber(getDefaultVoiceSubId());
}
/** @hide */
@@ -736,7 +791,10 @@
return getPhoneId(getDefaultVoiceSubId());
}
- /** @hide */
+ /**
+ * @return subId of the DefaultSms subscription or the value INVALID_SUB_ID if an error.
+ * @hide - to be unhidden
+ */
public static long getDefaultSmsSubId() {
long subId = INVALID_SUB_ID;
@@ -768,7 +826,7 @@
/** @hide */
public static SubInfoRecord getDefaultSmsSubInfo() {
- return getSubInfoUsingSubId(getDefaultSmsSubId());
+ return getSubInfoForSubscriber(getDefaultSmsSubId());
}
/** @hide */
@@ -808,7 +866,7 @@
/** @hide */
public static SubInfoRecord getDefaultDataSubInfo() {
- return getSubInfoUsingSubId(getDefaultDataSubId());
+ return getSubInfoForSubscriber(getDefaultDataSubId());
}
/** @hide */
@@ -862,7 +920,10 @@
}
}
- /** @hide */
+ /**
+ * @return true if a valid subId else false
+ * @hide - to be unhidden
+ */
public static boolean isValidSubId(long subId) {
return subId > INVALID_SUB_ID ;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index cdee3de..164fc3c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -608,7 +608,7 @@
public String getDeviceId(int slotId) {
long[] subId = SubscriptionManager.getSubId(slotId);
try {
- return getSubscriberInfo().getDeviceIdUsingSubId(subId[0]);
+ return getSubscriberInfo().getDeviceIdForSubscriber(subId[0]);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -639,7 +639,7 @@
public String getImei(int slotId) {
long[] subId = SubscriptionManager.getSubId(slotId);
try {
- return getSubscriberInfo().getImeiUsingSubId(subId[0]);
+ return getSubscriberInfo().getImeiForSubscriber(subId[0]);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -703,7 +703,7 @@
/** @hide */
public void enableLocationUpdates(long subId) {
try {
- getITelephony().enableLocationUpdatesUsingSubId(subId);
+ getITelephony().enableLocationUpdatesForSubscriber(subId);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -725,7 +725,7 @@
/** @hide */
public void disableLocationUpdates(long subId) {
try {
- getITelephony().disableLocationUpdatesUsingSubId(subId);
+ getITelephony().disableLocationUpdatesForSubscriber(subId);
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -772,6 +772,7 @@
*
* {@hide}
*/
+ @SystemApi
public int getCurrentPhoneType() {
return getCurrentPhoneType(getDefaultSubscription());
}
@@ -786,12 +787,13 @@
* @param subId for which phone type is returned
*/
/** {@hide} */
+ @SystemApi
public int getCurrentPhoneType(long subId) {
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getActivePhoneTypeUsingSubId(subId);
+ return telephony.getActivePhoneTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return getPhoneTypeFromProperty(subId);
@@ -1157,7 +1159,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getNetworkTypeUsingSubId(subId);
+ return telephony.getNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1211,7 +1213,7 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getDataNetworkTypeUsingSubId(subId);
+ return telephony.getDataNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1243,7 +1245,7 @@
try{
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getVoiceNetworkTypeUsingSubId(subId);
+ return telephony.getVoiceNetworkTypeForSubscriber(subId);
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_UNKNOWN;
@@ -1570,7 +1572,7 @@
/** {@hide} */
public String getSimSerialNumber(long subId) {
try {
- return getSubscriberInfo().getIccSerialNumberUsingSubId(subId);
+ return getSubscriberInfo().getIccSerialNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1606,7 +1608,7 @@
/** {@hide} */
public int getLteOnCdmaMode(long subId) {
try {
- return getITelephony().getLteOnCdmaModeUsingSubId(subId);
+ return getITelephony().getLteOnCdmaModeForSubscriber(subId);
} catch (RemoteException ex) {
// Assume no ICC card if remote exception which shouldn't happen
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
@@ -1646,7 +1648,7 @@
/** {@hide} */
public String getSubscriberId(long subId) {
try {
- return getSubscriberInfo().getSubscriberIdUsingSubId(subId);
+ return getSubscriberInfo().getSubscriberIdForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1685,7 +1687,7 @@
/** {@hide} */
public String getGroupIdLevel1(long subId) {
try {
- return getSubscriberInfo().getGroupIdLevel1UsingSubId(subId);
+ return getSubscriberInfo().getGroupIdLevel1ForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1726,7 +1728,7 @@
return number;
}
try {
- return getSubscriberInfo().getLine1NumberUsingSubId(subId);
+ return getSubscriberInfo().getLine1NumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1809,7 +1811,7 @@
return alphaTag;
}
try {
- return getSubscriberInfo().getLine1AlphaTagUsingSubId(subId);
+ return getSubscriberInfo().getLine1AlphaTagForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1843,7 +1845,7 @@
/** {@hide} */
public String getMsisdn(long subId) {
try {
- return getSubscriberInfo().getMsisdnUsingSubId(subId);
+ return getSubscriberInfo().getMsisdnForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1873,7 +1875,7 @@
/** {@hide} */
public String getVoiceMailNumber(long subId) {
try {
- return getSubscriberInfo().getVoiceMailNumberUsingSubId(subId);
+ return getSubscriberInfo().getVoiceMailNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1905,7 +1907,7 @@
/** {@hide} */
public String getCompleteVoiceMailNumber(long subId) {
try {
- return getSubscriberInfo().getCompleteVoiceMailNumberUsingSubId(subId);
+ return getSubscriberInfo().getCompleteVoiceMailNumberForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1935,7 +1937,7 @@
/** {@hide} */
public int getVoiceMessageCount(long subId) {
try {
- return getITelephony().getVoiceMessageCountUsingSubId(subId);
+ return getITelephony().getVoiceMessageCountForSubscriber(subId);
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -1967,7 +1969,7 @@
/** {@hide} */
public String getVoiceMailAlphaTag(long subId) {
try {
- return getSubscriberInfo().getVoiceMailAlphaTagUsingSubId(subId);
+ return getSubscriberInfo().getVoiceMailAlphaTagForSubscriber(subId);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2057,7 +2059,7 @@
/** {@hide} */
public int getCallState(long subId) {
try {
- return getITelephony().getCallStateUsingSubId(subId);
+ return getITelephony().getCallStateForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return CALL_STATE_IDLE;
@@ -2179,7 +2181,7 @@
String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
try {
Boolean notifyNow = (getITelephony() != null);
- sRegistry.listenUsingSubId(listener.mSubId, pkgForDebug, listener.callback, events, notifyNow);
+ sRegistry.listenForSubscriber(listener.mSubId, pkgForDebug, listener.callback, events, notifyNow);
} catch (RemoteException ex) {
// system process dead
} catch (NullPointerException ex) {
@@ -2202,7 +2204,7 @@
/** {@hide} */
public int getCdmaEriIconIndex(long subId) {
try {
- return getITelephony().getCdmaEriIconIndexUsingSubId(subId);
+ return getITelephony().getCdmaEriIconIndexForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -2230,7 +2232,7 @@
/** {@hide} */
public int getCdmaEriIconMode(long subId) {
try {
- return getITelephony().getCdmaEriIconModeUsingSubId(subId);
+ return getITelephony().getCdmaEriIconModeForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return -1;
@@ -2255,7 +2257,7 @@
/** {@hide} */
public String getCdmaEriText(long subId) {
try {
- return getITelephony().getCdmaEriTextUsingSubId(subId);
+ return getITelephony().getCdmaEriTextForSubscriber(subId);
} catch (RemoteException ex) {
// the phone process is restarting.
return null;
@@ -2511,9 +2513,9 @@
* @param content String containing SAT/USAT response in hexadecimal
* format starting with command tag. See TS 102 223 for
* details.
- * @return The APDU response from the ICC card, with the last 4 bytes
- * being the status word. If the command fails, returns an empty
- * string.
+ * @return The APDU response from the ICC card in hexadecimal format
+ * with the last 4 bytes being the status word. If the command fails,
+ * returns an empty string.
*/
public String sendEnvelopeWithStatus(String content) {
try {
@@ -2903,27 +2905,6 @@
}
/**
- * Get the calculated preferred network type.
- * Used for debugging incorrect network type.
- * <p>
- * Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- *
- * @return the preferred network type, defined in RILConstants.java or -1 if
- * none available.
- */
- public int getCalculatedPreferredNetworkType() {
- try {
- return getITelephony().getCalculatedPreferredNetworkType();
- } catch (RemoteException ex) {
- Rlog.e(TAG, "getCalculatedPreferredNetworkType RemoteException", ex);
- } catch (NullPointerException ex) {
- Rlog.e(TAG, "getCalculatedPreferredNetworkType NPE", ex);
- }
- return -1;
- }
-
- /**
* Get the preferred network type.
* Used for device configuration by some CDMA operators.
* <p>
@@ -2932,6 +2913,7 @@
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @return the preferred network type, defined in RILConstants.java.
+ * @hide
*/
public int getPreferredNetworkType() {
try {
@@ -2954,6 +2936,7 @@
*
* @param networkType the preferred network type, defined in RILConstants.java.
* @return true on success; false on any failure.
+ * @hide
*/
public boolean setPreferredNetworkType(int networkType) {
try {
@@ -2967,25 +2950,17 @@
}
/**
- * Set the CDMA subscription source.
- * Used for device supporting both NV and RUIM for CDMA.
+ * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
+ *
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
- * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
* @return true on success; false on any failure.
*/
- public boolean setCdmaSubscription(int subscriptionType) {
- try {
- return getITelephony().setCdmaSubscription(subscriptionType);
- } catch (RemoteException ex) {
- Rlog.e(TAG, "setCdmaSubscription RemoteException", ex);
- } catch (NullPointerException ex) {
- Rlog.e(TAG, "setCdmaSubscription NPE", ex);
- }
- return false;
+ public boolean setGlobalPreferredNetworkType() {
+ return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA);
}
/**
@@ -3023,9 +2998,9 @@
}
/**
- * Override the branding for the input ICCID.
+ * Override the branding for the current ICCID.
*
- * Once set, whenever the ICCID is inserted into the device, the service
+ * Once set, whenever the SIM is present in the device, the service
* provider name (SPN) and the operator name will both be replaced by the
* brand value input. To unset the value, the same function should be
* called with a null brand value.
@@ -3034,14 +3009,12 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* or has to be carrier app - see #hasCarrierPrivileges.
*
- * @param iccId The ICCID of that the branding applies to.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
- public boolean setOperatorBrandOverride(String iccId, String brand) {
- // TODO: Validate ICCID format.
+ public boolean setOperatorBrandOverride(String brand) {
try {
- return getITelephony().setOperatorBrandOverride(iccId, brand);
+ return getITelephony().setOperatorBrandOverride(brand);
} catch (RemoteException ex) {
Rlog.e(TAG, "setOperatorBrandOverride RemoteException", ex);
} catch (NullPointerException ex) {
@@ -3393,6 +3366,7 @@
* Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param enable true means enabling the simplified UI.
+ * @hide
*/
public void enableSimplifiedNetworkSettings(boolean enable) {
enableSimplifiedNetworkSettings(getDefaultSubscription(), enable);
@@ -3408,6 +3382,7 @@
*
* @param subId for which the simplified UI should be enabled or disabled.
* @param enable true means enabling the simplified UI.
+ * @hide
*/
public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
try {
@@ -3424,6 +3399,7 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @return true if the simplified UI is enabled.
+ * @hide
*/
public boolean getSimplifiedNetworkSettingsEnabled() {
return getSimplifiedNetworkSettingsEnabled(getDefaultSubscription());
@@ -3437,6 +3413,7 @@
*
* @param subId for which the simplified UI should be enabled or disabled.
* @return true if the simplified UI is enabled.
+ * @hide
*/
public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
try {
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index 4cba70d..d1c8ef0 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -609,16 +609,25 @@
}
} else {
if (prevWasEscape) {
- char shiftChar = shiftTableToChar.charAt(c);
+ char shiftChar =
+ c < shiftTableToChar.length() ? shiftTableToChar.charAt(c) : ' ';
if (shiftChar == ' ') {
// display character from main table if not present in shift table
- ret.append(languageTableToChar.charAt(c));
+ if (c < languageTableToChar.length()) {
+ ret.append(languageTableToChar.charAt(c));
+ } else {
+ ret.append(' ');
+ }
} else {
ret.append(shiftChar);
}
} else {
if (!isMbcs || c < 0x80 || i + 1 >= offset + length) {
- ret.append(languageTableToChar.charAt(c));
+ if (c < languageTableToChar.length()) {
+ ret.append(languageTableToChar.charAt(c));
+ } else {
+ ret.append(' ');
+ }
} else {
// isMbcs must be true. So both mbcsBuffer and charset are initialized.
mbcsBuffer.clear();
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index 63b7a53..4337012 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -40,7 +40,7 @@
* broadcast when the message is successfully sent, or failed
*/
void sendMessage(long subId, String callingPkg, in Uri contentUri,
- String locationUrl, in ContentValues configOverrides, in PendingIntent sentIntent);
+ String locationUrl, in Bundle configOverrides, in PendingIntent sentIntent);
/**
* Download an MMS message using known location and transaction id
@@ -57,7 +57,7 @@
* broadcast when the message is downloaded, or the download is failed
*/
void downloadMessage(long subId, String callingPkg, String locationUrl,
- in Uri contentUri, in ContentValues configOverrides,
+ in Uri contentUri, in Bundle configOverrides,
in PendingIntent downloadedIntent);
/**
@@ -192,7 +192,7 @@
* broadcast when the message is successfully sent, or failed
*/
void sendStoredMessage(long subId, String callingPkg, in Uri messageUri,
- in ContentValues configOverrides, in PendingIntent sentIntent);
+ in Bundle configOverrides, in PendingIntent sentIntent);
/**
* Turns on/off the flag to automatically write sent/received SMS/MMS messages into system
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 552abaf..c203442 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -31,12 +31,12 @@
* Retrieves the unique device ID of a subId for the device, e.g., IMEI
* for GSM phones.
*/
- String getDeviceIdUsingSubId(long subId);
+ String getDeviceIdForSubscriber(long subId);
/**
* Retrieves the IMEI.
*/
- String getImeiUsingSubId(long subId);
+ String getImeiForSubscriber(long subId);
/**
* Retrieves the software version number for the device, e.g., IMEI/SV
@@ -52,7 +52,7 @@
/**
* Retrieves the unique subscriber ID of a given subId, e.g., IMSI for GSM phones.
*/
- String getSubscriberIdUsingSubId(long subId);
+ String getSubscriberIdForSubscriber(long subId);
/**
* Retrieves the Group Identifier Level1 for GSM phones.
@@ -62,7 +62,7 @@
/**
* Retrieves the Group Identifier Level1 for GSM phones of a subId.
*/
- String getGroupIdLevel1UsingSubId(long subId);
+ String getGroupIdLevel1ForSubscriber(long subId);
/**
* Retrieves the serial number of the ICC, if applicable.
@@ -72,7 +72,7 @@
/**
* Retrieves the serial number of a given subId.
*/
- String getIccSerialNumberUsingSubId(long subId);
+ String getIccSerialNumberForSubscriber(long subId);
/**
* Retrieves the phone number string for line 1.
@@ -82,7 +82,7 @@
/**
* Retrieves the phone number string for line 1 of a subcription.
*/
- String getLine1NumberUsingSubId(long subId);
+ String getLine1NumberForSubscriber(long subId);
/**
@@ -93,7 +93,7 @@
/**
* Retrieves the alpha identifier for line 1 of a subId.
*/
- String getLine1AlphaTagUsingSubId(long subId);
+ String getLine1AlphaTagForSubscriber(long subId);
/**
@@ -104,7 +104,7 @@
/**
* Retrieves the Msisdn of a subId.
*/
- String getMsisdnUsingSubId(long subId);
+ String getMsisdnForSubscriber(long subId);
/**
* Retrieves the voice mail number.
@@ -114,7 +114,7 @@
/**
* Retrieves the voice mail number of a given subId.
*/
- String getVoiceMailNumberUsingSubId(long subId);
+ String getVoiceMailNumberForSubscriber(long subId);
/**
* Retrieves the complete voice mail number.
@@ -124,7 +124,7 @@
/**
* Retrieves the complete voice mail number for particular subId
*/
- String getCompleteVoiceMailNumberUsingSubId(long subId);
+ String getCompleteVoiceMailNumberForSubscriber(long subId);
/**
* Retrieves the alpha identifier associated with the voice mail number.
@@ -135,7 +135,7 @@
* Retrieves the alpha identifier associated with the voice mail number
* of a subId.
*/
- String getVoiceMailAlphaTagUsingSubId(long subId);
+ String getVoiceMailAlphaTagForSubscriber(long subId);
/**
* Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index abbdc4a..32bb8b4 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -47,7 +47,7 @@
* @param subId the subId id.
* @return list of SmsRawData of all sms on ICC
*/
- List<SmsRawData> getAllMessagesFromIccEfUsingSubId(in long subId, String callingPkg);
+ List<SmsRawData> getAllMessagesFromIccEfForSubscriber(in long subId, String callingPkg);
/**
* Update the specified message on the ICC.
@@ -75,7 +75,7 @@
* @return success or not
*
*/
- boolean updateMessageOnIccEfUsingSubId(in long subId, String callingPkg,
+ boolean updateMessageOnIccEfForSubscriber(in long subId, String callingPkg,
int messageIndex, int newStatus, in byte[] pdu);
/**
@@ -99,7 +99,7 @@
* @return success or not
*
*/
- boolean copyMessageToIccEfUsingSubId(in long subId, String callingPkg, int status,
+ boolean copyMessageToIccEfForSubscriber(in long subId, String callingPkg, int status,
in byte[] pdu, in byte[] smsc);
/**
@@ -152,7 +152,7 @@
* raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId id.
*/
- void sendDataUsingSubId(long subId, String callingPkg, in String destAddr,
+ void sendDataForSubscriber(long subId, String callingPkg, in String destAddr,
in String scAddr, in int destPort, in byte[] data, in PendingIntent sentIntent,
in PendingIntent deliveryIntent);
@@ -206,7 +206,7 @@
* raw pdu of the status report is in the extended data ("pdu").
* @param subId the subId on which the SMS has to be sent.
*/
- void sendTextUsingSubId(in long subId, String callingPkg, in String destAddr,
+ void sendTextForSubscriber(in long subId, String callingPkg, in String destAddr,
in String scAddr, in String text, in PendingIntent sentIntent,
in PendingIntent deliveryIntent);
@@ -283,7 +283,7 @@
* extended data ("pdu").
* @param subId the subId on which the SMS has to be sent.
*/
- void sendMultipartTextUsingSubId(in long subId, String callingPkg,
+ void sendMultipartTextForSubscriber(in long subId, String callingPkg,
in String destinationAddress, in String scAddress,
in List<String> parts, in List<PendingIntent> sentIntents,
in List<PendingIntent> deliveryIntents);
@@ -315,7 +315,7 @@
*
* @see #disableCellBroadcast(int)
*/
- boolean enableCellBroadcastUsingSubId(in long subId, int messageIdentifier);
+ boolean enableCellBroadcastForSubscriber(in long subId, int messageIdentifier);
/**
* Disable reception of cell broadcast (SMS-CB) messages with the given
@@ -344,7 +344,7 @@
*
* @see #enableCellBroadcast(int)
*/
- boolean disableCellBroadcastUsingSubId(in long subId, int messageIdentifier);
+ boolean disableCellBroadcastForSubscriber(in long subId, int messageIdentifier);
/*
* Enable reception of cell broadcast (SMS-CB) messages with the given
@@ -377,7 +377,7 @@
*
* @see #disableCellBroadcastRange(int, int)
*/
- boolean enableCellBroadcastRangeUsingSubId(long subId, int startMessageId, int endMessageId);
+ boolean enableCellBroadcastRangeForSubscriber(long subId, int startMessageId, int endMessageId);
/**
* Disable reception of cell broadcast (SMS-CB) messages with the given
@@ -410,7 +410,7 @@
*
* @see #enableCellBroadcastRange(int, int, int)
*/
- boolean disableCellBroadcastRangeUsingSubId(long subId, int startMessageId,
+ boolean disableCellBroadcastRangeForSubscriber(long subId, int startMessageId,
int endMessageId);
/**
@@ -423,7 +423,7 @@
* Returns the premium SMS send permission for the specified package.
* Requires system permission.
*/
- int getPremiumSmsPermissionUsingSubId(long subId, String packageName);
+ int getPremiumSmsPermissionForSubscriber(long subId, String packageName);
/**
* Set the SMS send permission for the specified package.
@@ -439,7 +439,7 @@
* Set the SMS send permission for the specified package.
* Requires system permission.
*/
- void setPremiumSmsPermissionUsingSubId(long subId, String packageName, int permission);
+ void setPremiumSmsPermissionForSubscriber(long subId, String packageName, int permission);
/**
* SMS over IMS is supported if IMS is registered and SMS is supported
@@ -459,7 +459,7 @@
*
* @see #getImsSmsFormat()
*/
- boolean isImsSmsSupportedUsingSubId(long subId);
+ boolean isImsSmsSupportedForSubscriber(long subId);
/*
* get user prefered SMS subId
@@ -489,7 +489,7 @@
*
* @see #isImsSmsSupported()
*/
- String getImsSmsFormatUsingSubId(long subId);
+ String getImsSmsFormatForSubscriber(long subId);
/*
* Get SMS prompt property, enabled or not
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index e3b7d59..b87365e 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -1,18 +1,18 @@
/*
-* Copyright (C) 2011-2014 MediaTek Inc.
-*
-* 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.
-*/
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.internal.telephony;
@@ -22,15 +22,13 @@
interface ISub {
/**
* Get the SubInfoRecord according to an index
- * @param context Context provided by caller
* @param subId The unique SubInfoRecord index in database
* @return SubInfoRecord, maybe null
*/
- SubInfoRecord getSubInfoUsingSubId(long subId);
+ SubInfoRecord getSubInfoForSubscriber(long subId);
/**
* Get the SubInfoRecord according to an IccId
- * @param context Context provided by caller
* @param iccId the IccId of SIM card
* @return SubInfoRecord, maybe null
*/
@@ -38,7 +36,6 @@
/**
* Get the SubInfoRecord according to slotId
- * @param context Context provided by caller
* @param slotId the slot which the SIM is inserted
* @return SubInfoRecord, maybe null
*/
@@ -46,35 +43,30 @@
/**
* Get all the SubInfoRecord(s) in subinfo database
- * @param context Context provided by caller
* @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
*/
List<SubInfoRecord> getAllSubInfoList();
/**
* Get the SubInfoRecord(s) of the currently inserted SIM(s)
- * @param context Context provided by caller
* @return Array list of currently inserted SubInfoRecord(s)
*/
List<SubInfoRecord> getActiveSubInfoList();
/**
* Get the SUB count of all SUB(s) in subinfo database
- * @param context Context provided by caller
* @return all SIM count in database, include what was inserted before
*/
int getAllSubInfoCount();
/**
* Get the count of active SUB(s)
- * @param context Context provided by caller
* @return active SIM count
*/
int getActiveSubInfoCount();
/**
* Add a new SubInfoRecord to subinfo database if needed
- * @param context Context provided by caller
* @param iccId the IccId of the SIM card
* @param slotId the slot which the SIM is inserted
* @return the URL of the newly created row or the updated row
@@ -83,7 +75,6 @@
/**
* Set SIM color by simInfo index
- * @param context Context provided by caller
* @param color the color of the SIM
* @param subId the unique SubInfoRecord index in database
* @return the number of records updated
@@ -92,7 +83,6 @@
/**
* Set display name by simInfo index
- * @param context Context provided by caller
* @param displayName the display name of SIM card
* @param subId the unique SubInfoRecord index in database
* @return the number of records updated
@@ -101,7 +91,6 @@
/**
* Set display name by simInfo index with name source
- * @param context Context provided by caller
* @param displayName the display name of SIM card
* @param subId the unique SubInfoRecord index in database
* @param nameSource, 0: DEFAULT_SOURCE, 1: SIM_SOURCE, 2: USER_INPUT
@@ -111,7 +100,6 @@
/**
* Set phone number by subId
- * @param context Context provided by caller
* @param number the phone number of the SIM
* @param subId the unique SubInfoRecord index in database
* @return the number of records updated
@@ -120,7 +108,6 @@
/**
* Set number display format. 0: none, 1: the first four digits, 2: the last four digits
- * @param context Context provided by caller
* @param format the display format of phone number
* @param subId the unique SubInfoRecord index in database
* @return the number of records updated
@@ -129,7 +116,6 @@
/**
* Set data roaming by simInfo index
- * @param context Context provided by caller
* @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
* @param subId the unique SubInfoRecord index in database
* @return the number of records updated
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5c3dcdb..5b280ff 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -59,7 +59,7 @@
* @param subId user preferred subId.
* @return whether it hung up
*/
- boolean endCallUsingSubId(long subId);
+ boolean endCallForSubscriber(long subId);
/**
* Answer the currently-ringing call.
@@ -103,7 +103,7 @@
* @param subId user preferred subId.
* @return true if the phone state is OFFHOOK.
*/
- boolean isOffhookUsingSubId(long subId);
+ boolean isOffhookForSubscriber(long subId);
/**
* Check if an incoming phone call is ringing or call waiting
@@ -112,7 +112,7 @@
* @param subId user preferred subId.
* @return true if the phone state is RINGING.
*/
- boolean isRingingUsingSubId(long subId);
+ boolean isRingingForSubscriber(long subId);
/**
* Check if an incoming phone call is ringing or call waiting.
@@ -132,7 +132,7 @@
* @param subId user preferred subId.
* @return true if the phone state is IDLE.
*/
- boolean isIdleUsingSubId(long subId);
+ boolean isIdleForSubscriber(long subId);
/**
* Check to see if the radio is on or not.
@@ -145,7 +145,7 @@
* @param subId user preferred subId.
* @return returns true if the radio is on.
*/
- boolean isRadioOnUsingSubId(long subId);
+ boolean isRadioOnForSubscriber(long subId);
/**
* Check if the SIM pin lock is enabled.
@@ -167,7 +167,7 @@
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
- boolean supplyPinUsingSubId(long subId, String pin);
+ boolean supplyPinForSubscriber(long subId, String pin);
/**
* Supply puk to unlock the SIM and set SIM pin to new pin.
@@ -186,7 +186,7 @@
* @param subId user preferred subId.
* @return whether the operation was a success.
*/
- boolean supplyPukUsingSubId(long subId, String puk, String pin);
+ boolean supplyPukForSubscriber(long subId, String puk, String pin);
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
@@ -204,7 +204,7 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPinReportResultUsingSubId(long subId, String pin);
+ int[] supplyPinReportResultForSubscriber(long subId, String pin);
/**
* Supply puk to unlock the SIM and set SIM pin to new pin.
@@ -226,7 +226,7 @@
* @return retValue[0] = Phone.PIN_RESULT_SUCCESS on success. Otherwise error code
* retValue[1] = number of attempts remaining if known otherwise -1
*/
- int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin);
+ int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin);
/**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
@@ -245,7 +245,7 @@
* @param subId user preferred subId.
* @return true if MMI command is executed.
*/
- boolean handlePinMmiUsingSubId(long subId, String dialString);
+ boolean handlePinMmiForSubscriber(long subId, String dialString);
/**
* Toggles the radio on or off.
@@ -256,7 +256,7 @@
* Toggles the radio on or off on particular subId.
* @param subId user preferred subId.
*/
- void toggleRadioOnOffUsingSubId(long subId);
+ void toggleRadioOnOffForSubscriber(long subId);
/**
* Set the radio to on or off
@@ -267,7 +267,7 @@
* Set the radio to on or off on particular subId.
* @param subId user preferred subId.
*/
- boolean setRadioUsingSubId(long subId, boolean turnOn);
+ boolean setRadioForSubscriber(long subId, boolean turnOn);
/**
* Set the radio to on or off unconditionally
@@ -283,7 +283,7 @@
* Request to update location information for a subscrition in service state
* @param subId user preferred subId.
*/
- void updateServiceLocationUsingSubId(long subId);
+ void updateServiceLocationForSubscriber(long subId);
/**
* Enable location update notifications.
@@ -294,7 +294,7 @@
* Enable location update notifications.
* @param subId user preferred subId.
*/
- void enableLocationUpdatesUsingSubId(long subId);
+ void enableLocationUpdatesForSubscriber(long subId);
/**
* Disable location update notifications.
@@ -305,7 +305,7 @@
* Disable location update notifications.
* @param subId user preferred subId.
*/
- void disableLocationUpdatesUsingSubId(long subId);
+ void disableLocationUpdatesForSubscriber(long subId);
/**
* Allow mobile data connections.
@@ -334,7 +334,7 @@
/**
* Returns the call state for a subId.
*/
- int getCallStateUsingSubId(long subId);
+ int getCallStateForSubscriber(long subId);
int getDataActivity();
int getDataState();
@@ -352,7 +352,7 @@
* and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
* @param subId user preferred subId.
*/
- int getActivePhoneTypeUsingSubId(long subId);
+ int getActivePhoneTypeForSubscriber(long subId);
/**
* Returns the CDMA ERI icon index to display
@@ -363,7 +363,7 @@
* Returns the CDMA ERI icon index to display on particular subId.
* @param subId user preferred subId.
*/
- int getCdmaEriIconIndexUsingSubId(long subId);
+ int getCdmaEriIconIndexForSubscriber(long subId);
/**
* Returns the CDMA ERI icon mode,
@@ -378,7 +378,7 @@
* 1 - FLASHING
* @param subId user preferred subId.
*/
- int getCdmaEriIconModeUsingSubId(long subId);
+ int getCdmaEriIconModeForSubscriber(long subId);
/**
* Returns the CDMA ERI text,
@@ -389,7 +389,7 @@
* Returns the CDMA ERI text for particular subId,
* @param subId user preferred subId.
*/
- String getCdmaEriTextUsingSubId(long subId);
+ String getCdmaEriTextForSubscriber(long subId);
/**
* Returns true if OTA service provisioning needs to run.
@@ -408,7 +408,7 @@
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountUsingSubId(long subId);
+ int getVoiceMessageCountForSubscriber(long subId);
/**
* Returns the network type for data transmission
@@ -420,7 +420,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getNetworkTypeUsingSubId(long subId);
+ int getNetworkTypeForSubscriber(long subId);
/**
* Returns the network type for data transmission
@@ -432,7 +432,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getDataNetworkTypeUsingSubId(long subId);
+ int getDataNetworkTypeForSubscriber(long subId);
/**
* Returns the network type for voice
@@ -444,7 +444,7 @@
* @param subId user preferred subId.
* Returns the network type
*/
- int getVoiceNetworkTypeUsingSubId(long subId);
+ int getVoiceNetworkTypeForSubscriber(long subId);
/**
* Return true if an ICC card is present
@@ -476,7 +476,7 @@
* @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
* or {@link PHone#LTE_ON_CDMA_TRUE}
*/
- int getLteOnCdmaModeUsingSubId(long subId);
+ int getLteOnCdmaModeForSubscriber(long subId);
/**
* Returns the all observed cell information of the device.
@@ -643,15 +643,6 @@
boolean setPreferredNetworkType(int networkType);
/**
- * Set the CDMA subscription source.
- * Used for device supporting both NV and RUIM for CDMA.
- *
- * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
- * @return true on success; false on any failure.
- */
- boolean setCdmaSubscription(int subscriptionType);
-
- /**
* User enable/disable Mobile Data.
*
* @param enable true to turn on, else false
@@ -766,9 +757,9 @@
String getLine1AlphaTagForDisplay(long subId);
/**
- * Override the operator branding for the input ICCID.
+ * Override the operator branding for the current ICCID.
*
- * Once set, whenever the ICCID is inserted into the device, the service
+ * Once set, whenever the SIM is present in the device, the service
* provider name (SPN) and the operator name will both be replaced by the
* brand value input. To unset the value, the same function should be
* called with a null brand value.
@@ -777,11 +768,10 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* or has to be carrier app - see #hasCarrierPrivileges.
*
- * @param iccid The ICCID of that the branding applies to.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
- boolean setOperatorBrandOverride(String iccId, String brand);
+ boolean setOperatorBrandOverride(String brand);
/**
* Returns the result and response from RIL for oem request
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index fd2d1c7..d776833 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -30,30 +30,30 @@
interface ITelephonyRegistry {
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
- void listenUsingSubId(in long subId, String pkg, IPhoneStateListener callback, int events,
+ void listenForSubscriber(in long subId, String pkg, IPhoneStateListener callback, int events,
boolean notifyNow);
void notifyCallState(int state, String incomingNumber);
- void notifyCallStateUsingSubId(in long subId, int state, String incomingNumber);
+ void notifyCallStateForSubscriber(in long subId, int state, String incomingNumber);
void notifyServiceState(in ServiceState state);
- void notifyServiceStateUsingSubId(in long subId, in ServiceState state);
+ void notifyServiceStateForSubscriber(in long subId, in ServiceState state);
void notifySignalStrength(in SignalStrength signalStrength);
- void notifySignalStrengthUsingSubId(in long subId, in SignalStrength signalStrength);
+ void notifySignalStrengthForSubscriber(in long subId, in SignalStrength signalStrength);
void notifyMessageWaitingChanged(boolean mwi);
- void notifyMessageWaitingChangedUsingSubId(in long subId, boolean mwi);
+ void notifyMessageWaitingChangedForSubscriber(in long subId, boolean mwi);
void notifyCallForwardingChanged(boolean cfi);
- void notifyCallForwardingChangedUsingSubId(in long subId, boolean cfi);
+ void notifyCallForwardingChangedForSubscriber(in long subId, boolean cfi);
void notifyDataActivity(int state);
- void notifyDataActivityUsingSubId(in long subId, int state);
+ void notifyDataActivityForSubscriber(in long subId, int state);
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
- void notifyDataConnectionUsingSubId(long subId, int state, boolean isDataConnectivityPossible,
+ void notifyDataConnectionForSubscriber(long subId, int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, in LinkProperties linkProperties,
in NetworkCapabilities networkCapabilities, int networkType, boolean roaming);
void notifyDataConnectionFailed(String reason, String apnType);
- void notifyDataConnectionFailedUsingSubId(long subId, String reason, String apnType);
+ void notifyDataConnectionFailedForSubscriber(long subId, String reason, String apnType);
void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationUsingSubId(in long subId, in Bundle cellLocation);
+ void notifyCellLocationForSubscriber(in long subId, in Bundle cellLocation);
void notifyOtaspChanged(in int otaspMode);
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
@@ -61,7 +61,7 @@
void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
String failCause);
- void notifyCellInfoUsingSubId(in long subId, in List<CellInfo> cellInfo);
+ void notifyCellInfoForSubscriber(in long subId, in List<CellInfo> cellInfo);
void notifyDataConnectionRealTimeInfo(in DataConnectionRealTimeInfo dcRtInfo);
void notifyVoLteServiceStateChanged(in VoLteServiceState lteState);
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 5ec4247..c89208d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -123,8 +123,8 @@
/** Indicate the timer value for exiting emergency callback mode */
static final String PROPERTY_ECM_EXIT_TIMER = "ro.cdma.ecmexittimer";
- /** The international dialing prefix conversion string */
- static final String PROPERTY_IDP_STRING = "ro.cdma.idpstring";
+ /** the international dialing prefix of current operator network */
+ static final String PROPERTY_OPERATOR_IDP_STRING = "gsm.operator.idpstring";
/**
* Defines the schema for the carrier specified OTASP number
diff --git a/test-runner/src/android/test/ProviderTestCase.java b/test-runner/src/android/test/ProviderTestCase.java
index 1b323cf..4108f34 100644
--- a/test-runner/src/android/test/ProviderTestCase.java
+++ b/test-runner/src/android/test/ProviderTestCase.java
@@ -67,9 +67,8 @@
filenamePrefix);
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
- mProvider = mProviderClass.newInstance();
- mProvider.attachInfoForTesting(mProviderContext, null);
- assertNotNull(mProvider);
+ mProvider = ProviderTestCase2.createProviderForTest(
+ mProviderContext, mProviderClass, mProviderAuthority);
mResolver.addProvider(mProviderAuthority, getProvider());
}
@@ -107,8 +106,7 @@
resolver, targetContextWrapper);
DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
- T provider = providerClass.newInstance();
- provider.attachInfoForTesting(context, null);
+ T provider = ProviderTestCase2.createProviderForTest(context, providerClass, authority);
resolver.addProvider(authority, provider);
return resolver;
diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java
index dcd089da..1fa633e 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -19,6 +19,7 @@
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.test.mock.MockContext;
import android.test.mock.MockContentResolver;
@@ -138,14 +139,24 @@
getContext(), // The context that file methods are delegated to
filenamePrefix);
mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
-
- mProvider = mProviderClass.newInstance();
- mProvider.attachInfoForTesting(mProviderContext, null);
- assertNotNull(mProvider);
+ mProvider = createProviderForTest(mProviderContext, mProviderClass, mProviderAuthority);
mResolver.addProvider(mProviderAuthority, getProvider());
}
/**
+ * Creates and sets up a new instance of the provider.
+ */
+ static <T extends ContentProvider> T createProviderForTest(
+ Context context, Class<T> providerClass, String authority)
+ throws IllegalAccessException, InstantiationException {
+ T instance = providerClass.newInstance();
+ ProviderInfo providerInfo = new ProviderInfo();
+ providerInfo.authority = authority;
+ instance.attachInfoForTesting(context, providerInfo);
+ return instance;
+ }
+
+ /**
* Tears down the environment for the test fixture.
* <p>
* Calls {@link android.content.ContentProvider#shutdown()} on the
@@ -218,8 +229,7 @@
Context context = new IsolatedContext(resolver, targetContextWrapper);
DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
- T provider = providerClass.newInstance();
- provider.attachInfoForTesting(context, null);
+ T provider = createProviderForTest(context, providerClass, authority);
resolver.addProvider(authority, provider);
return resolver;
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index cd7d178..5a4e0eb 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -46,7 +46,7 @@
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.UserHandle;
@@ -403,6 +403,29 @@
}
@Override
+ public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
+ Rect badgeLocation,
+ int badgeDensity) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** @hide */
+ @Override
+ public Drawable getUserBadgeForDensity(UserHandle user, int density) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
throw new UnsupportedOperationException();
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index e03b9c8..6837d22 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -30,7 +30,6 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.BitmapFactory;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -74,7 +73,7 @@
Intent intent = new Intent(ActivityTestMain.this, SpamActivity.class);
Bundle options = null;
if (fg) {
- ActivityOptions opts = ActivityOptions.makeLaunchTaskBehindAnimation();
+ ActivityOptions opts = ActivityOptions.makeTaskLaunchBehind();
options = opts.toBundle();
}
startActivity(intent, options);
@@ -391,6 +390,17 @@
}
@Override
+ protected void onPause() {
+ super.onPause();
+ Log.i(TAG, "I'm such a slooow poor loser");
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+ Log.i(TAG, "See?");
+ }
+
+ @Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mOverrideConfig != null) {
diff --git a/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java b/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
index c630bad..d513f44 100644
--- a/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
+++ b/tests/Camera2Tests/CameraToo/src/com/example/android/camera2/cameratoo/CameraTooActivity.java
@@ -290,14 +290,14 @@
// Open the camera device
try {
- mCameraManager.openCamera(mCameraId, mCameraStateListener,
+ mCameraManager.openCamera(mCameraId, mCameraStateCallback,
mBackgroundHandler);
} catch (CameraAccessException ex) {
Log.e(TAG, "Failed to configure output surface", ex);
}
mGotSecondCallback = true;
- // Control flow continues in mCameraStateListener.onOpened()
+ // Control flow continues in mCameraStateCallback.onOpened()
}
}};
@@ -305,8 +305,8 @@
* Calledbacks invoked upon state changes in our {@code CameraDevice}. <p>These are run on
* {@code mBackgroundThread}.</p>
*/
- final CameraDevice.StateListener mCameraStateListener =
- new CameraDevice.StateListener() {
+ final CameraDevice.StateCallback mCameraStateCallback =
+ new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice camera) {
Log.i(TAG, "Successfully opened camera");
@@ -337,8 +337,8 @@
* Callbacks invoked upon state changes in our {@code CameraCaptureSession}. <p>These are run on
* {@code mBackgroundThread}.</p>
*/
- final CameraCaptureSession.StateListener mCaptureSessionListener =
- new CameraCaptureSession.StateListener() {
+ final CameraCaptureSession.StateCallback mCaptureSessionListener =
+ new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
Log.i(TAG, "Finished configuring camera outputs");
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
index 05057f2..07dfb54 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/samples/simplecamera/Camera2Source.java
@@ -38,7 +38,7 @@
import android.view.Surface;
import com.android.ex.camera2.blocking.BlockingCameraManager;
import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
-import com.android.ex.camera2.blocking.BlockingSessionListener;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
import androidx.media.filterfw.Filter;
import androidx.media.filterfw.Frame;
import androidx.media.filterfw.FrameImage2D;
@@ -72,7 +72,7 @@
private static final long SESSION_TIMEOUT_MS = 2000;
- class MyCameraListener extends CameraManager.AvailabilityListener {
+ class MyCameraListener extends CameraManager.AvailabilityCallback {
@Override
public void onCameraAvailable(String cameraId) {
@@ -88,7 +88,7 @@
}
- class MyCaptureListener extends CameraCaptureSession.CaptureListener {
+ class MyCaptureCallback extends CameraCaptureSession.CaptureCallback {
@Override
public void onCaptureCompleted(CameraCaptureSession camera, CaptureRequest request,
@@ -189,7 +189,7 @@
surfaces.add(mSurface);
CaptureRequest.Builder mCaptureRequest = null;
try {
- BlockingSessionListener blkSession = new BlockingSessionListener();
+ BlockingSessionCallback blkSession = new BlockingSessionCallback();
mCamera.createCaptureSession(surfaces, blkSession, mHandler);
mCaptureRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -203,7 +203,7 @@
}
try {
- mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureListener(),
+ mCameraSession.setRepeatingRequest(mCaptureRequest.build(), new MyCaptureCallback(),
mHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
index 3360e30..256a1d4 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RevealActivity.java
@@ -17,6 +17,7 @@
package com.android.test.hwui;
import android.animation.Animator;
+import android.animation.AnimatorSet;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
@@ -34,6 +35,7 @@
private static final int DURATION = 800;
private boolean mShouldBlock;
+ private int mIteration = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -57,10 +59,17 @@
Animator animator = ViewAnimationUtils.createCircularReveal(view,
view.getWidth() / 2, view.getHeight() / 2,
0, Math.max(view.getWidth(), view.getHeight()));
- animator.setDuration(DURATION);
- animator.setAllowRunningAsynchronously(true);
- animator.start();
+ if (mIteration < 2) {
+ animator.setDuration(DURATION);
+ animator.start();
+ } else {
+ AnimatorSet set = new AnimatorSet();
+ set.playTogether(animator);
+ set.setDuration(DURATION);
+ set.start();
+ }
+ mIteration = (mIteration + 1) % 4;
mShouldBlock = !mShouldBlock;
if (mShouldBlock) {
view.post(sBlockThread);
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
index 50633db..4e18ce9 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/AppListFragment.java
@@ -94,7 +94,7 @@
// Load the data
final PackageManager pm = context.getPackageManager();
- final Intent intent = new Intent(MediaBrowserService.SERVICE_ACTION);
+ final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
final List<ResolveInfo> list = pm.queryIntentServices(intent, 0);
final int N = list.size();
mItems = new ArrayList(N);
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
index a216a32..4e2e47e 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -134,8 +134,8 @@
bob.setSubtitle("Summary " + i);
bob.setMediaId(Uri.withAppendedPath(BASE_URI,
Integer.toString(i)).toString());
- list.add(new MediaBrowser.MediaItem(MediaBrowser.MediaItem.FLAG_BROWSABLE,
- bob.build()));
+ list.add(new MediaBrowser.MediaItem(bob.build(),
+ MediaBrowser.MediaItem.FLAG_BROWSABLE));
}
result.sendResult(list);
diff --git a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
index d1172ac..ceb0937 100644
--- a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
+++ b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
@@ -76,7 +76,7 @@
* destroyed before {@link #onStop} is called.
*/
public void onStart() {
- mController.addCallback(mCb);
+ mController.registerCallback(mCb);
IntentFilter filter = new IntentFilter();
filter.addAction(RequestUtils.ACTION_FFWD);
filter.addAction(RequestUtils.ACTION_NEXT);
@@ -100,7 +100,7 @@
*/
public void onStop() {
mStarted = false;
- mController.removeCallback(mCb);
+ mController.unregisterCallback(mCb);
mService.unregisterReceiver(this);
updateNotification();
}
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index c8d72ca..7861bcc 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -159,7 +159,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
if (mController != null) {
- mController.removeCallback(mControllerCb);
+ mController.unregisterCallback(mControllerCb);
}
mBinder = null;
mController = null;
@@ -185,7 +185,7 @@
}
mController = new MediaController(mContext, token);
mContext.setMediaController(mController);
- mController.addCallback(mControllerCb, mHandler);
+ mController.registerCallback(mControllerCb, mHandler);
mTransportControls = mController.getTransportControls();
if (mArt != null) {
setArt(mArt);
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 69fefeb..5f7467a 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -6,6 +6,8 @@
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
LOCAL_PACKAGE_NAME := UsageStatsTest
include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/res/layout/config_row_item.xml b/tests/UsageStatsTest/res/layout/config_row_item.xml
new file mode 100644
index 0000000..547de04
--- /dev/null
+++ b/tests/UsageStatsTest/res/layout/config_row_item.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"/>
diff --git a/tests/UsageStatsTest/res/layout/row_item.xml b/tests/UsageStatsTest/res/layout/row_item.xml
index da50163..4f2bfe4 100644
--- a/tests/UsageStatsTest/res/layout/row_item.xml
+++ b/tests/UsageStatsTest/res/layout/row_item.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
@@ -8,13 +9,10 @@
<TextView android:id="@android:id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
+ android:layout_weight="1"
android:textStyle="bold"/>
<TextView android:id="@android:id/text2"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignBaseline="@android:id/text1"/>
-</RelativeLayout>
+ android:layout_height="wrap_content"/>
+</LinearLayout>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
index 5f62ad8..31e7c38 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageLogActivity.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
+import android.support.v4.util.CircularArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -35,11 +36,14 @@
private UsageStatsManager mUsageStatsManager;
private Adapter mAdapter;
private Handler mHandler = new Handler();
+ private long mLastTime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
+ mLastTime = System.currentTimeMillis() - USAGE_STATS_PERIOD;
+
mAdapter = new Adapter();
setListAdapter(mAdapter);
}
@@ -59,24 +63,31 @@
@Override
public void run() {
long now = System.currentTimeMillis();
- long beginTime = now - USAGE_STATS_PERIOD;
- UsageEvents events = mUsageStatsManager.queryEvents(beginTime, now);
- mAdapter.update(events);
+ UsageEvents events = mUsageStatsManager.queryEvents(mLastTime, now);
+ long lastEventTime = mAdapter.update(events);
+ if (lastEventTime >= 0) {
+ mLastTime = lastEventTime + 1;
+ }
mHandler.postDelayed(this, 1000 * 5);
}
private class Adapter extends BaseAdapter {
+ private static final int MAX_EVENTS = 50;
+ private final CircularArray<UsageEvents.Event> mEvents = new CircularArray<>(MAX_EVENTS);
- private final ArrayList<UsageEvents.Event> mEvents = new ArrayList<>();
-
- public void update(UsageEvents results) {
- mEvents.clear();
+ public long update(UsageEvents results) {
+ long lastTimeStamp = -1;
while (results.hasNextEvent()) {
UsageEvents.Event event = new UsageEvents.Event();
results.getNextEvent(event);
- mEvents.add(event);
+ lastTimeStamp = event.getTimeStamp();
+ if (mEvents.size() == MAX_EVENTS) {
+ mEvents.popLast();
+ }
+ mEvents.addFirst(event);
}
notifyDataSetChanged();
+ return lastTimeStamp;
}
@Override
@@ -85,7 +96,7 @@
}
@Override
- public Object getItem(int position) {
+ public UsageEvents.Event getItem(int position) {
return mEvents.get(position);
}
@@ -95,41 +106,72 @@
}
@Override
+ public int getItemViewType(int position) {
+ final int eventType = getItem(position).getEventType();
+ if (eventType == UsageEvents.Event.CONFIGURATION_CHANGE) {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
public View getView(int position, View convertView, ViewGroup parent) {
+ final UsageEvents.Event event = getItem(position);
+
final ViewHolder holder;
if (convertView == null) {
- convertView = LayoutInflater.from(UsageLogActivity.this)
- .inflate(R.layout.row_item, parent, false);
holder = new ViewHolder();
- holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
- holder.state = (TextView) convertView.findViewById(android.R.id.text2);
+
+ if (event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
+ convertView = LayoutInflater.from(UsageLogActivity.this)
+ .inflate(R.layout.config_row_item, parent, false);
+ holder.config = (TextView) convertView.findViewById(android.R.id.text1);
+ } else {
+ convertView = LayoutInflater.from(UsageLogActivity.this)
+ .inflate(R.layout.row_item, parent, false);
+ holder.packageName = (TextView) convertView.findViewById(android.R.id.text1);
+ holder.state = (TextView) convertView.findViewById(android.R.id.text2);
+ }
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
- holder.packageName.setText(mEvents.get(position).getPackageName());
- String state;
- switch (mEvents.get(position).getEventType()) {
+ if (holder.packageName != null) {
+ holder.packageName.setText(event.getPackageName());
+ }
+
+ if (holder.state != null) {
+ holder.state.setText(eventToString(event.getEventType()));
+ }
+
+ if (holder.config != null &&
+ event.getEventType() == UsageEvents.Event.CONFIGURATION_CHANGE) {
+ holder.config.setText(event.getConfiguration().toString());
+ }
+ return convertView;
+ }
+
+ private String eventToString(int eventType) {
+ switch (eventType) {
case UsageEvents.Event.MOVE_TO_FOREGROUND:
- state = "Foreground";
- break;
+ return "Foreground";
case UsageEvents.Event.MOVE_TO_BACKGROUND:
- state = "Background";
- break;
+ return "Background";
+
+ case UsageEvents.Event.CONFIGURATION_CHANGE:
+ return "Config change";
default:
- state = "Unknown: " + mEvents.get(position).getEventType();
- break;
+ return "Unknown: " + eventType;
}
- holder.state.setText(state);
- return convertView;
}
}
static class ViewHolder {
public TextView packageName;
public TextView state;
+ public TextView config;
}
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 1f01461..4639114 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -92,7 +92,7 @@
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_UNENROLLED:
Log.i(TAG, "STATE_KEYPHRASE_UNENROLLED");
- Intent enroll = mHotwordDetector.createIntentToEnroll();
+ Intent enroll = mHotwordDetector.createEnrollIntent();
Log.i(TAG, "Need to enroll with " + enroll);
break;
case AlwaysOnHotwordDetector.STATE_KEYPHRASE_ENROLLED:
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
new file mode 100644
index 0000000..b4259cd
--- /dev/null
+++ b/tests/WallpaperTest/Android.mk
@@ -0,0 +1,15 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := WallpaperTest
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+include $(BUILD_PACKAGE)
+
diff --git a/tests/WallpaperTest/AndroidManifest.xml b/tests/WallpaperTest/AndroidManifest.xml
new file mode 100644
index 0000000..4c914dd
--- /dev/null
+++ b/tests/WallpaperTest/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.wallpapertest" >
+
+ <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+
+ <application
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service
+ android:label="@string/test_wallpaper"
+ android:name=".TestWallpaper"
+ android:permission="android.permission.BIND_WALLPAPER"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.service.wallpaper.WallpaperService" />
+ </intent-filter>
+ <meta-data android:name="android.service.wallpaper"
+ android:resource="@xml/test_wallpaper" />
+ </service>
+ </application>
+</manifest>
diff --git a/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png b/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png
new file mode 100644
index 0000000..df92eb5
--- /dev/null
+++ b/tests/WallpaperTest/res/drawable-hdpi/test_wallpaper_thumb.png
Binary files differ
diff --git a/tests/WallpaperTest/res/layout/activity_main.xml b/tests/WallpaperTest/res/layout/activity_main.xml
new file mode 100644
index 0000000..d968396
--- /dev/null
+++ b/tests/WallpaperTest/res/layout/activity_main.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/window_background">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/dimens"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/width"/>
+ <EditText
+ android:id="@+id/dimen_width"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/height"/>
+ <EditText
+ android:id="@+id/dimen_height"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/wallpaper_offset"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/x"/>
+ <EditText
+ android:id="@+id/walloff_x"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/y"/>
+ <EditText
+ android:id="@+id/walloff_y"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/padding"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/left"/>
+ <EditText
+ android:id="@+id/padding_left"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/right"/>
+ <EditText
+ android:id="@+id/padding_right"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/top"/>
+ <EditText
+ android:id="@+id/padding_top"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/bottom"/>
+ <EditText
+ android:id="@+id/padding_bottom"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="number"/>
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/display_offset"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/x"/>
+ <EditText
+ android:id="@+id/dispoff_x"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberSigned"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="15dp"
+ android:textSize="17sp"
+ android:text="@string/y"/>
+ <EditText
+ android:id="@+id/dispoff_y"
+ android:layout_width="60sp"
+ android:layout_height="wrap_content"
+ android:inputType="numberSigned"/>
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/tests/WallpaperTest/res/values-v11/styles.xml b/tests/WallpaperTest/res/values-v11/styles.xml
new file mode 100644
index 0000000..95000b2
--- /dev/null
+++ b/tests/WallpaperTest/res/values-v11/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Wallpaper">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values-v21/styles.xml b/tests/WallpaperTest/res/values-v21/styles.xml
new file mode 100644
index 0000000..e42d526
--- /dev/null
+++ b/tests/WallpaperTest/res/values-v21/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme for API 21+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Material.Wallpaper">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values/colors.xml b/tests/WallpaperTest/res/values/colors.xml
new file mode 100644
index 0000000..8c08249
--- /dev/null
+++ b/tests/WallpaperTest/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+<resources>
+ <color name="window_background">#80000000</color>
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/values/strings.xml b/tests/WallpaperTest/res/values/strings.xml
new file mode 100644
index 0000000..fd21259
--- /dev/null
+++ b/tests/WallpaperTest/res/values/strings.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2014 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.
+-->
+
+<resources>
+ <string name="app_name">Wallpaper Test</string>
+
+ <string name="test_wallpaper">Test Wallpaper</string>
+ <string name="test_wallpaper_author">Google</string>
+ <string name="test_wallpaper_desc">
+ Test wallpaper for use with the wallpaper test app.
+ </string>
+
+ <string name="dimens">Dimens: </string>
+ <string name="width">Width: </string>
+ <string name="height">Height: </string>
+
+ <string name="wallpaper_offset">Wall off: </string>
+ <string name="x">X: </string>
+ <string name="y">Y: </string>
+
+ <string name="padding">Padding: </string>
+ <string name="left">Left: </string>
+ <string name="right">Right: </string>
+ <string name="top">Top: </string>
+ <string name="bottom">Bottom: </string>
+
+ <string name="display_offset">Disp off: </string>
+</resources>
diff --git a/tests/WallpaperTest/res/values/styles.xml b/tests/WallpaperTest/res/values/styles.xml
new file mode 100644
index 0000000..d2b91d6
--- /dev/null
+++ b/tests/WallpaperTest/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2013 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.
+-->
+
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Wallpaper">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/tests/WallpaperTest/res/xml/test_wallpaper.xml b/tests/WallpaperTest/res/xml/test_wallpaper.xml
new file mode 100644
index 0000000..9f7d714
--- /dev/null
+++ b/tests/WallpaperTest/res/xml/test_wallpaper.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2008, 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.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- about the polar clock. -->
+
+<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
+ android:author="@string/test_wallpaper_author"
+ android:description="@string/test_wallpaper_desc"
+ android:thumbnail="@drawable/test_wallpaper_thumb" />
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
new file mode 100644
index 0000000..7880f67
--- /dev/null
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/MainActivity.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2014 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.example.wallpapertest;
+
+import android.app.Activity;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+ private static final String TAG = "MainActivity";
+
+ WallpaperManager mWallpaperManager;
+ WindowManager mWindowManager;
+
+ TextView mDimenWidthView;
+ TextView mDimenHeightView;
+
+ TextView mWallOffXView;
+ TextView mWallOffYView;
+
+ TextView mPaddingLeftView;
+ TextView mPaddingRightView;
+ TextView mPaddingTopView;
+ TextView mPaddingBottomView;
+
+ TextView mDispOffXView;
+ TextView mDispOffYView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mWallpaperManager = (WallpaperManager)getSystemService(Context.WALLPAPER_SERVICE);
+ mWindowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
+
+ mDimenWidthView = (TextView) findViewById(R.id.dimen_width);
+ mDimenWidthView.addTextChangedListener(mTextWatcher);
+ mDimenHeightView = (TextView) findViewById(R.id.dimen_height);
+ mDimenHeightView.addTextChangedListener(mTextWatcher);
+
+ mWallOffXView = (TextView) findViewById(R.id.walloff_x);
+ mWallOffXView.addTextChangedListener(mTextWatcher);
+ mWallOffYView = (TextView) findViewById(R.id.walloff_y);
+ mWallOffYView.addTextChangedListener(mTextWatcher);
+
+ mPaddingLeftView = (TextView) findViewById(R.id.padding_left);
+ mPaddingLeftView.addTextChangedListener(mTextWatcher);
+ mPaddingRightView = (TextView) findViewById(R.id.padding_right);
+ mPaddingRightView.addTextChangedListener(mTextWatcher);
+ mPaddingTopView = (TextView) findViewById(R.id.padding_top);
+ mPaddingTopView.addTextChangedListener(mTextWatcher);
+ mPaddingBottomView = (TextView) findViewById(R.id.padding_bottom);
+ mPaddingBottomView.addTextChangedListener(mTextWatcher);
+
+ mDispOffXView = (TextView) findViewById(R.id.dispoff_x);
+ mDispOffXView.addTextChangedListener(mTextWatcher);
+ mDispOffYView = (TextView) findViewById(R.id.dispoff_y);
+ mDispOffYView.addTextChangedListener(mTextWatcher);
+
+ updateDimens();
+ updateWallOff();
+ updatePadding();
+ updateDispOff();
+ }
+
+ private int loadPropIntText(TextView view, int baseVal) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ float fval = Float.parseFloat(str);
+ return (int)(fval*baseVal);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return baseVal;
+ }
+
+ private float loadFloatText(TextView view) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ return Float.parseFloat(str);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return 0;
+ }
+
+ private int loadIntText(TextView view) {
+ String str = view.getText().toString();
+ if (str != null && !TextUtils.isEmpty(str)) {
+ try {
+ return Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ Log.i(TAG, "Bad number: " + str, e);
+ }
+ }
+ return 0;
+ }
+
+ public void updateDimens() {
+ Point minDims = new Point();
+ Point maxDims = new Point();
+ mWindowManager.getDefaultDisplay().getCurrentSizeRange(minDims, maxDims);
+ mWallpaperManager.suggestDesiredDimensions(
+ loadPropIntText(mDimenWidthView, maxDims.x),
+ loadPropIntText(mDimenHeightView, maxDims.y));
+ }
+
+ public void updateWallOff() {
+ IBinder token = getWindow().getDecorView().getWindowToken();
+ if (token != null) {
+ mWallpaperManager.setWallpaperOffsets(token, loadFloatText(mWallOffXView),
+ loadFloatText(mWallOffYView));
+ }
+ }
+
+ public void updatePadding() {
+ Rect padding = new Rect();
+ padding.left = loadIntText(mPaddingLeftView);
+ padding.top = loadIntText(mPaddingTopView);
+ padding.right = loadIntText(mPaddingRightView);
+ padding.bottom = loadIntText(mPaddingBottomView);
+ mWallpaperManager.setDisplayPadding(padding);
+ }
+
+ public void updateDispOff() {
+ IBinder token = getWindow().getDecorView().getWindowToken();
+ if (token != null) {
+ mWallpaperManager.setDisplayOffset(token, loadIntText(mDispOffXView),
+ loadIntText(mDispOffYView));
+ }
+ }
+
+ final TextWatcher mTextWatcher = new TextWatcher() {
+ @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
+ updateDimens();
+ updateWallOff();
+ updatePadding();
+ updateDispOff();
+ }
+
+ @Override public void afterTextChanged(Editable s) {
+ }
+ };
+}
diff --git a/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java b/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java
new file mode 100644
index 0000000..95db6d1
--- /dev/null
+++ b/tests/WallpaperTest/src/com/example/wallpapertest/TestWallpaper.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2014 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.example.wallpapertest;
+
+import android.service.wallpaper.WallpaperService;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Paint;
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.text.TextPaint;
+import android.view.SurfaceHolder;
+import android.content.res.XmlResourceParser;
+
+import android.os.Handler;
+import android.util.Log;
+
+import android.view.WindowInsets;
+
+public class TestWallpaper extends WallpaperService {
+ private static final String LOG_TAG = "PolarClock";
+
+ private final Handler mHandler = new Handler();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ public Engine onCreateEngine() {
+ return new ClockEngine();
+ }
+
+ class ClockEngine extends Engine {
+ private static final int OUTER_COLOR = 0xffff0000;
+ private static final int INNER_COLOR = 0xff000080;
+ private static final int STABLE_COLOR = 0xa000ff00;
+ private static final int TEXT_COLOR = 0xa0ffffff;
+
+ private final Paint.FontMetrics mTextMetrics = new Paint.FontMetrics();
+
+ private int mPadding;
+
+ private final Rect mMainInsets = new Rect();
+ private final Rect mStableInsets = new Rect();
+ private boolean mRound = false;
+
+ private int mDesiredWidth;
+ private int mDesiredHeight;
+
+ private float mOffsetX;
+ private float mOffsetY;
+ private float mOffsetXStep;
+ private float mOffsetYStep;
+ private int mOffsetXPixels;
+ private int mOffsetYPixels;
+
+ private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Paint mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+
+ private final Runnable mDrawClock = new Runnable() {
+ public void run() {
+ drawFrame();
+ }
+ };
+ private boolean mVisible;
+
+ ClockEngine() {
+ }
+
+ @Override
+ public void onCreate(SurfaceHolder surfaceHolder) {
+ super.onCreate(surfaceHolder);
+
+ mDesiredWidth = getDesiredMinimumWidth();
+ mDesiredHeight = getDesiredMinimumHeight();
+
+ Paint paint = mFillPaint;
+ paint.setStyle(Paint.Style.FILL);
+
+ paint = mStrokePaint;
+ paint.setStrokeWidth(3);
+ paint.setStrokeCap(Paint.Cap.ROUND);
+ paint.setStyle(Paint.Style.STROKE);
+
+ TextPaint tpaint = mTextPaint;
+ tpaint.density = getResources().getDisplayMetrics().density;
+ tpaint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
+ tpaint.setColor(TEXT_COLOR);
+ tpaint.setTextSize(18 * getResources().getDisplayMetrics().scaledDensity);
+ tpaint.setShadowLayer(4 * getResources().getDisplayMetrics().density, 0, 0, 0xff000000);
+
+ mTextPaint.getFontMetrics(mTextMetrics);
+
+ mPadding = (int)(16 * getResources().getDisplayMetrics().density);
+
+ if (isPreview()) {
+ mOffsetX = 0.5f;
+ mOffsetY = 0.5f;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mHandler.removeCallbacks(mDrawClock);
+ }
+
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+ mVisible = visible;
+ if (!visible) {
+ mHandler.removeCallbacks(mDrawClock);
+ }
+ drawFrame();
+ }
+
+ @Override
+ public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ super.onSurfaceChanged(holder, format, width, height);
+ drawFrame();
+ }
+
+ @Override
+ public void onSurfaceCreated(SurfaceHolder holder) {
+ super.onSurfaceCreated(holder);
+ }
+
+ @Override
+ public void onSurfaceDestroyed(SurfaceHolder holder) {
+ super.onSurfaceDestroyed(holder);
+ mVisible = false;
+ mHandler.removeCallbacks(mDrawClock);
+ }
+
+ @Override
+ public void onApplyWindowInsets(WindowInsets insets) {
+ super.onApplyWindowInsets(insets);
+ mMainInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
+ insets.getStableInsetRight(), insets.getStableInsetBottom());
+ mRound = insets.isRound();
+ drawFrame();
+ }
+
+ @Override
+ public void onDesiredSizeChanged(int desiredWidth, int desiredHeight) {
+ super.onDesiredSizeChanged(desiredWidth, desiredHeight);
+ mDesiredWidth = desiredWidth;
+ mDesiredHeight = desiredHeight;
+ drawFrame();
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset,
+ float xStep, float yStep, int xPixels, int yPixels) {
+ super.onOffsetsChanged(xOffset, yOffset, xStep, yStep, xPixels, yPixels);
+
+ if (isPreview()) return;
+
+ mOffsetX = xOffset;
+ mOffsetY = yOffset;
+ mOffsetXStep = xStep;
+ mOffsetYStep = yStep;
+ mOffsetXPixels = xPixels;
+ mOffsetYPixels = yPixels;
+
+ drawFrame();
+ }
+
+ void drawFrame() {
+ final SurfaceHolder holder = getSurfaceHolder();
+ final Rect frame = holder.getSurfaceFrame();
+ final int width = frame.width();
+ final int height = frame.height();
+
+ Canvas c = null;
+ try {
+ c = holder.lockCanvas();
+ if (c != null) {
+ final Paint paint = mFillPaint;
+
+ paint.setColor(OUTER_COLOR);
+ c.drawRect(0, 0, width, height, paint);
+
+ paint.setColor(INNER_COLOR);
+ c.drawRect(0+mMainInsets.left, 0+mMainInsets.top,
+ width-mMainInsets.right, height-mMainInsets.bottom, paint);
+
+ mStrokePaint.setColor(STABLE_COLOR);
+ c.drawRect(0 + mStableInsets.left, 0 + mStableInsets.top,
+ width - mStableInsets.right, height - mStableInsets.bottom,
+ mStrokePaint);
+
+ final int ascdesc = (int)(-mTextMetrics.ascent + mTextMetrics.descent);
+ final int linegap = (int)(-mTextMetrics.ascent + mTextMetrics.descent
+ + mTextMetrics.leading);
+
+ int x = mStableInsets.left + mPadding;
+ int y = height - mStableInsets.bottom - mPadding - ascdesc;
+ c.drawText("Surface Size: " + width + " x " + height,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Desired Size: " + mDesiredWidth + " x " + mDesiredHeight,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Raw: " + mOffsetX + ", " + mOffsetY,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Step: " + mOffsetXStep + ", " + mOffsetYStep,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Cur Offset Pixels: " + mOffsetXPixels + ", " + mOffsetYPixels,
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("Stable Insets: (" + mStableInsets.left + ", " + mStableInsets.top
+ + ") - (" + mStableInsets.right + ", " + mStableInsets.bottom + ")",
+ x, y, mTextPaint);
+ y -= linegap;
+ c.drawText("System Insets: (" + mMainInsets.left + ", " + mMainInsets.top
+ + ") - (" + mMainInsets.right + ", " + mMainInsets.bottom + ")",
+ x, y, mTextPaint);
+
+ }
+ } finally {
+ if (c != null) holder.unlockCanvasAndPost(c);
+ }
+ }
+ }
+}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b3c364b..8341de6 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2574,8 +2574,12 @@
continue;
}
const size_t N = t->getOrderedConfigs().size();
- sp<AaptSymbols> typeSymbols;
- typeSymbols = outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ sp<AaptSymbols> typeSymbols =
+ outSymbols->addNestedSymbol(String8(t->getName()), t->getPos());
+ if (typeSymbols == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
for (size_t ci=0; ci<N; ci++) {
sp<ConfigList> c = t->getOrderedConfigs().itemAt(ci);
if (c == NULL) {
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 6bb28e1..393d2ec 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -20,15 +20,20 @@
Usage: apilint.py current.txt
Usage: apilint.py current.txt previous.txt
+
+You can also splice in blame details like this:
+$ git blame api/current.txt -t -e > /tmp/currentblame.txt
+$ apilint.py /tmp/currentblame.txt previous.txt --no-color
"""
-import re, sys, collections
+import re, sys, collections, traceback
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False):
# manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes
+ if "--no-color" in sys.argv: return ""
codes = []
if reset: codes.append("0")
else:
@@ -43,9 +48,10 @@
class Field():
- def __init__(self, clazz, raw):
+ def __init__(self, clazz, raw, blame):
self.clazz = clazz
self.raw = raw.strip(" {;")
+ self.blame = blame
raw = raw.split()
self.split = list(raw)
@@ -60,14 +66,20 @@
else:
self.value = None
+ self.ident = self.raw.replace(" deprecated ", " ")
+
def __repr__(self):
return self.raw
class Method():
- def __init__(self, clazz, raw):
+ def __init__(self, clazz, raw, blame):
self.clazz = clazz
self.raw = raw.strip(" {;")
+ self.blame = blame
+
+ # drop generics for now
+ raw = re.sub("<.+?>", "", raw)
raw = re.split("[\s(),;]+", raw)
for r in ["", ";"]:
@@ -84,14 +96,24 @@
if r == "throws": break
self.args.append(r)
+ # identity for compat purposes
+ ident = self.raw
+ ident = ident.replace(" deprecated ", " ")
+ ident = ident.replace(" synchronized ", " ")
+ ident = re.sub("<.+?>", "", ident)
+ if " throws " in ident:
+ ident = ident[:ident.index(" throws ")]
+ self.ident = ident
+
def __repr__(self):
return self.raw
class Class():
- def __init__(self, pkg, raw):
+ def __init__(self, pkg, raw, blame):
self.pkg = pkg
self.raw = raw.strip(" {;")
+ self.blame = blame
self.ctors = []
self.fields = []
self.methods = []
@@ -102,19 +124,25 @@
self.fullname = raw[raw.index("class")+1]
elif "interface" in raw:
self.fullname = raw[raw.index("interface")+1]
-
- if "." in self.fullname:
- self.name = self.fullname[self.fullname.rindex(".")+1:]
else:
- self.name = self.fullname
+ raise ValueError("Funky class type %s" % (self.raw))
+
+ if "extends" in raw:
+ self.extends = raw[raw.index("extends")+1]
+ else:
+ self.extends = None
+
+ self.fullname = self.pkg.name + "." + self.fullname
+ self.name = self.fullname[self.fullname.rindex(".")+1:]
def __repr__(self):
return self.raw
class Package():
- def __init__(self, raw):
+ def __init__(self, raw, blame):
self.raw = raw.strip(" {;")
+ self.blame = blame
raw = raw.split()
self.name = raw[raw.index("package")+1]
@@ -124,55 +152,68 @@
def parse_api(fn):
- api = []
+ api = {}
pkg = None
clazz = None
+ blame = None
+
+ re_blame = re.compile("^([a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
with open(fn) as f:
for raw in f.readlines():
raw = raw.rstrip()
+ match = re_blame.match(raw)
+ if match is not None:
+ blame = match.groups()[0:2]
+ raw = match.groups()[2]
+ else:
+ blame = None
if raw.startswith("package"):
- pkg = Package(raw)
+ pkg = Package(raw, blame)
elif raw.startswith(" ") and raw.endswith("{"):
- clazz = Class(pkg, raw)
- api.append(clazz)
+ clazz = Class(pkg, raw, blame)
+ api[clazz.fullname] = clazz
elif raw.startswith(" ctor"):
- clazz.ctors.append(Method(clazz, raw))
+ clazz.ctors.append(Method(clazz, raw, blame))
elif raw.startswith(" method"):
- clazz.methods.append(Method(clazz, raw))
+ clazz.methods.append(Method(clazz, raw, blame))
elif raw.startswith(" field"):
- clazz.fields.append(Field(clazz, raw))
+ clazz.fields.append(Field(clazz, raw, blame))
return api
-failures = []
-
-def filter_dupe(s):
- return s.replace(" deprecated ", " ")
+failures = {}
def _fail(clazz, detail, msg):
"""Records an API failure to be processed later."""
global failures
+ sig = "%s-%s-%s" % (clazz.fullname, repr(detail), msg)
+ sig = sig.replace(" deprecated ", " ")
+
res = msg
+ blame = clazz.blame
if detail is not None:
res += "\n in " + repr(detail)
+ blame = detail.blame
res += "\n in " + repr(clazz)
res += "\n in " + repr(clazz.pkg)
- failures.append(filter_dupe(res))
+ if blame is not None:
+ res += "\n last modified by %s in %s" % (blame[1], blame[0])
+ failures[sig] = res
def warn(clazz, detail, msg):
- _fail(clazz, detail, "%sWarning:%s %s" % (format(fg=YELLOW, bg=BLACK), format(reset=True), msg))
+ _fail(clazz, detail, "%sWarning:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), format(reset=True), msg))
def error(clazz, detail, msg):
- _fail(clazz, detail, "%sError:%s %s" % (format(fg=RED, bg=BLACK), format(reset=True), msg))
+ _fail(clazz, detail, "%sError:%s %s" % (format(fg=RED, bg=BLACK, bold=True), format(reset=True), msg))
def verify_constants(clazz):
"""All static final constants must be FOO_NAME style."""
- if re.match("R\.[a-z]+", clazz.fullname): return
+ if re.match("android\.R\.[a-z]+", clazz.fullname): return
for f in clazz.fields:
if "static" in f.split and "final" in f.split:
@@ -188,6 +229,10 @@
def verify_class_names(clazz):
"""Try catching malformed class names like myMtp or MTPUser."""
+ if clazz.fullname.startswith("android.opengl"): return
+ if clazz.fullname.startswith("android.renderscript"): return
+ if re.match("android\.R\.[a-z]+", clazz.fullname): return
+
if re.search("[A-Z]{2,}", clazz.name) is not None:
warn(clazz, None, "Class name style should be Mtp not MTP")
if re.match("[^A-Z]", clazz.name):
@@ -196,32 +241,35 @@
def verify_method_names(clazz):
"""Try catching malformed method names, like Foo() or getMTU()."""
- if clazz.pkg.name == "android.opengl": return
+ if clazz.fullname.startswith("android.opengl"): return
+ if clazz.fullname.startswith("android.renderscript"): return
+ if clazz.fullname == "android.system.OsConstants": return
for m in clazz.methods:
if re.search("[A-Z]{2,}", m.name) is not None:
warn(clazz, m, "Method name style should be getMtu() instead of getMTU()")
if re.match("[^a-z]", m.name):
- error(clazz, None, "Method name must start with lowercase char")
+ error(clazz, m, "Method name must start with lowercase char")
def verify_callbacks(clazz):
"""Verify Callback classes.
All callback classes must be abstract.
All methods must follow onFoo() naming style."""
+ if clazz.fullname == "android.speech.tts.SynthesisCallback": return
if clazz.name.endswith("Callbacks"):
- error(clazz, None, "Class must be named exactly Callback")
+ error(clazz, None, "Class name must not be plural")
if clazz.name.endswith("Observer"):
- warn(clazz, None, "Class should be named Callback")
+ warn(clazz, None, "Class should be named FooCallback")
if clazz.name.endswith("Callback"):
if "interface" in clazz.split:
- error(clazz, None, "Callback must be abstract class")
+ error(clazz, None, "Callback must be abstract class to enable extension in future API levels")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "Callback method names must be onFoo style")
+ error(clazz, m, "Callback method names must be onFoo() style")
def verify_listeners(clazz):
@@ -233,16 +281,16 @@
if clazz.name.endswith("Listener"):
if " abstract class " in clazz.raw:
- error(clazz, None, "Listener should be interface")
+ error(clazz, None, "Listener should be an interface, otherwise renamed Callback")
for m in clazz.methods:
if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "Listener method names must be onFoo style")
+ error(clazz, m, "Listener method names must be onFoo() style")
if len(clazz.methods) == 1 and clazz.name.startswith("On"):
m = clazz.methods[0]
if (m.name + "Listener").lower() != clazz.name.lower():
- error(clazz, m, "Single method name should match class name")
+ error(clazz, m, "Single listener method name should match class name")
def verify_actions(clazz):
@@ -255,21 +303,24 @@
for f in clazz.fields:
if f.value is None: continue
if f.name.startswith("EXTRA_"): continue
+ if f.name == "SERVICE_INTERFACE" or f.name == "PROVIDER_INTERFACE": continue
if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower():
if not f.name.startswith("ACTION_"):
- error(clazz, f, "Intent action must be ACTION_FOO")
+ error(clazz, f, "Intent action constant name must be ACTION_FOO")
else:
- if clazz.name == "Intent":
+ if clazz.fullname == "android.content.Intent":
prefix = "android.intent.action"
- elif clazz.name == "Settings":
+ elif clazz.fullname == "android.provider.Settings":
prefix = "android.settings"
+ elif clazz.fullname == "android.app.admin.DevicePolicyManager" or clazz.fullname == "android.app.admin.DeviceAdminReceiver":
+ prefix = "android.app.action"
else:
prefix = clazz.pkg.name + ".action"
expected = prefix + "." + f.name[7:]
if f.value != expected:
- error(clazz, f, "Inconsistent action value")
+ error(clazz, f, "Inconsistent action value; expected %s" % (expected))
def verify_extras(clazz):
@@ -279,6 +330,9 @@
package android.foo {
String EXTRA_BAR = "android.foo.extra.BAR";
}"""
+ if clazz.fullname == "android.app.Notification": return
+ if clazz.fullname == "android.appwidget.AppWidgetManager": return
+
for f in clazz.fields:
if f.value is None: continue
if f.name.startswith("ACTION_"): continue
@@ -288,13 +342,15 @@
if not f.name.startswith("EXTRA_"):
error(clazz, f, "Intent extra must be EXTRA_FOO")
else:
- if clazz.name == "Intent":
+ if clazz.pkg.name == "android.content" and clazz.name == "Intent":
prefix = "android.intent.extra"
+ elif clazz.pkg.name == "android.app.admin":
+ prefix = "android.app.extra"
else:
prefix = clazz.pkg.name + ".extra"
expected = prefix + "." + f.name[6:]
if f.value != expected:
- error(clazz, f, "Inconsistent extra value")
+ error(clazz, f, "Inconsistent extra value; expected %s" % (expected))
def verify_equals(clazz):
@@ -303,7 +359,7 @@
eq = "equals" in methods
hc = "hashCode" in methods
if eq != hc:
- error(clazz, None, "Must override both equals and hashCode")
+ error(clazz, None, "Must override both equals and hashCode; missing one")
def verify_parcelable(clazz):
@@ -314,34 +370,59 @@
describe = [ i for i in clazz.methods if i.name == "describeContents" ]
if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
- error(clazz, None, "Parcelable requires CREATOR, writeToParcel, and describeContents")
+ error(clazz, None, "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
def verify_protected(clazz):
"""Verify that no protected methods are allowed."""
for m in clazz.methods:
if "protected" in m.split:
- error(clazz, m, "Protected method")
+ error(clazz, m, "No protected methods; must be public")
for f in clazz.fields:
if "protected" in f.split:
- error(clazz, f, "Protected field")
+ error(clazz, f, "No protected fields; must be public")
def verify_fields(clazz):
"""Verify that all exposed fields are final.
Exposed fields must follow myName style.
Catch internal mFoo objects being exposed."""
+
+ IGNORE_BARE_FIELDS = [
+ "android.app.ActivityManager.RecentTaskInfo",
+ "android.app.Notification",
+ "android.content.pm.ActivityInfo",
+ "android.content.pm.ApplicationInfo",
+ "android.content.pm.FeatureGroupInfo",
+ "android.content.pm.InstrumentationInfo",
+ "android.content.pm.PackageInfo",
+ "android.content.pm.PackageItemInfo",
+ "android.os.Message",
+ "android.system.StructPollfd",
+ ]
+
for f in clazz.fields:
if not "final" in f.split:
- error(clazz, f, "Bare fields must be final; consider adding accessors")
+ if clazz.fullname in IGNORE_BARE_FIELDS:
+ pass
+ elif clazz.fullname.endswith("LayoutParams"):
+ pass
+ elif clazz.fullname.startswith("android.util.Mutable"):
+ pass
+ else:
+ error(clazz, f, "Bare fields must be marked final; consider adding accessors")
if not "static" in f.split:
if not re.match("[a-z]([a-zA-Z]+)?", f.name):
- error(clazz, f, "Non-static fields must be myName")
+ error(clazz, f, "Non-static fields must be named with myField style")
- if re.match("[m][A-Z]", f.name):
+ if re.match("[ms][A-Z]", f.name):
error(clazz, f, "Don't expose your internal objects")
+ if re.match("[A-Z_]+", f.name):
+ if "static" not in f.split or "final" not in f.split:
+ error(clazz, f, "Constants must be marked static final")
+
def verify_register(clazz):
"""Verify parity of registration methods.
@@ -353,34 +434,34 @@
if m.name.startswith("register"):
other = "unregister" + m.name[8:]
if other not in methods:
- error(clazz, m, "Missing unregister")
+ error(clazz, m, "Missing unregister method")
if m.name.startswith("unregister"):
other = "register" + m.name[10:]
if other not in methods:
- error(clazz, m, "Missing register")
+ error(clazz, m, "Missing register method")
if m.name.startswith("add") or m.name.startswith("remove"):
- error(clazz, m, "Callback should be register/unregister")
+ error(clazz, m, "Callback methods should be named register/unregister")
if "Listener" in m.raw:
if m.name.startswith("add"):
other = "remove" + m.name[3:]
if other not in methods:
- error(clazz, m, "Missing remove")
+ error(clazz, m, "Missing remove method")
if m.name.startswith("remove") and not m.name.startswith("removeAll"):
other = "add" + m.name[6:]
if other not in methods:
- error(clazz, m, "Missing add")
+ error(clazz, m, "Missing add method")
if m.name.startswith("register") or m.name.startswith("unregister"):
- error(clazz, m, "Listener should be add/remove")
+ error(clazz, m, "Listener methods should be named add/remove")
def verify_sync(clazz):
"""Verify synchronized methods aren't exposed."""
for m in clazz.methods:
if "synchronized" in m.split:
- error(clazz, m, "Lock exposed")
+ error(clazz, m, "Internal lock exposed")
def verify_intent_builder(clazz):
@@ -392,7 +473,7 @@
if m.name.startswith("create") and m.name.endswith("Intent"):
pass
else:
- warn(clazz, m, "Should be createFooIntent()")
+ error(clazz, m, "Methods creating an Intent should be named createFooIntent()")
def verify_helper_classes(clazz):
@@ -402,25 +483,57 @@
if "extends android.app.Service" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Service"):
- error(clazz, None, "Inconsistent class name")
+ error(clazz, None, "Inconsistent class name; should be FooService")
+
+ found = False
+ for f in clazz.fields:
+ if f.name == "SERVICE_INTERFACE":
+ found = True
+ if f.value != clazz.fullname:
+ error(clazz, f, "Inconsistent interface constant; expected %s" % (clazz.fullname))
+
+ if not found:
+ warn(clazz, None, "Missing SERVICE_INTERFACE constant")
+
+ if "abstract" in clazz.split and not clazz.fullname.startswith("android.service."):
+ warn(clazz, None, "Services extended by developers should be under android.service")
+
if "extends android.content.ContentProvider" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Provider"):
- error(clazz, None, "Inconsistent class name")
+ error(clazz, None, "Inconsistent class name; should be FooProvider")
+
+ found = False
+ for f in clazz.fields:
+ if f.name == "PROVIDER_INTERFACE":
+ found = True
+ if f.value != clazz.fullname:
+ error(clazz, f, "Inconsistent interface name; expected %s" % (clazz.fullname))
+
+ if not found:
+ warn(clazz, None, "Missing PROVIDER_INTERFACE constant")
+
+ if "abstract" in clazz.split and not clazz.fullname.startswith("android.provider."):
+ warn(clazz, None, "Providers extended by developers should be under android.provider")
+
if "extends android.content.BroadcastReceiver" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Receiver"):
- error(clazz, None, "Inconsistent class name")
+ error(clazz, None, "Inconsistent class name; should be FooReceiver")
+
if "extends android.app.Activity" in clazz.raw:
test_methods = True
if not clazz.name.endswith("Activity"):
- error(clazz, None, "Inconsistent class name")
+ error(clazz, None, "Inconsistent class name; should be FooActivity")
if test_methods:
for m in clazz.methods:
if "final" in m.split: continue
if not re.match("on[A-Z]", m.name):
- error(clazz, m, "Extendable methods should be onFoo() style, otherwise final")
+ if "abstract" in m.split:
+ error(clazz, m, "Methods implemented by developers must be named onFoo()")
+ else:
+ warn(clazz, m, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
def verify_builder(clazz):
@@ -430,7 +543,7 @@
if not clazz.name.endswith("Builder"): return
if clazz.name != "Builder":
- warn(clazz, None, "Should be standalone Builder class")
+ warn(clazz, None, "Builder should be defined as inner class")
has_build = False
for m in clazz.methods:
@@ -442,11 +555,11 @@
if m.name.startswith("clear"): continue
if m.name.startswith("with"):
- error(clazz, m, "Builder methods must be setFoo()")
+ error(clazz, m, "Builder methods names must follow setFoo() style")
if m.name.startswith("set"):
if not m.typ.endswith(clazz.fullname):
- warn(clazz, m, "Should return the builder")
+ warn(clazz, m, "Methods should return the builder")
if not has_build:
warn(clazz, None, "Missing build() method")
@@ -474,7 +587,7 @@
"android.view",
"android.animation",
"android.provider",
- "android.content",
+ ["android.content","android.graphics.drawable"],
"android.database",
"android.graphics",
"android.text",
@@ -508,29 +621,40 @@
warn(clazz, m, "Method argument type violates package layering")
-def verify_boolean(clazz):
+def verify_boolean(clazz, api):
"""Catches people returning boolean from getFoo() style methods.
Ignores when matching setFoo() is present."""
+
methods = [ m.name for m in clazz.methods ]
+
+ builder = clazz.fullname + ".Builder"
+ builder_methods = []
+ if builder in api:
+ builder_methods = [ m.name for m in api[builder].methods ]
+
for m in clazz.methods:
if m.typ == "boolean" and m.name.startswith("get") and m.name != "get" and len(m.args) == 0:
setter = "set" + m.name[3:]
- if setter not in methods:
- error(clazz, m, "Methods returning boolean should be isFoo or hasFoo")
+ if setter in methods:
+ pass
+ elif builder is not None and setter in builder_methods:
+ pass
+ else:
+ warn(clazz, m, "Methods returning boolean should be named isFoo, hasFoo, areFoo")
def verify_collections(clazz):
"""Verifies that collection types are interfaces."""
+ if clazz.fullname == "android.os.Bundle": return
+
bad = ["java.util.Vector", "java.util.LinkedList", "java.util.ArrayList", "java.util.Stack",
"java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
for m in clazz.methods:
- filt = re.sub("<.+>", "", m.typ)
- if filt in bad:
- error(clazz, m, "Return type is concrete collection")
+ if m.typ in bad:
+ error(clazz, m, "Return type is concrete collection; should be interface")
for arg in m.args:
- filt = re.sub("<.+>", "", arg)
- if filt in bad:
- error(clazz, m, "Argument is concrete collection")
+ if arg in bad:
+ error(clazz, m, "Argument is concrete collection; should be interface")
def verify_flags(clazz):
@@ -545,15 +669,18 @@
scope = f.name[0:f.name.index("FLAG_")]
if val & known[scope]:
- warn(clazz, f, "Found overlapping flag")
+ warn(clazz, f, "Found overlapping flag constant value")
known[scope] |= val
-def verify_all(api):
+def verify_style(api):
+ """Find all style issues in the given API level."""
global failures
- failures = []
- for clazz in api:
+ failures = {}
+ for key in sorted(api.keys()):
+ clazz = api[key]
+
if clazz.pkg.name.startswith("java"): continue
if clazz.pkg.name.startswith("junit"): continue
if clazz.pkg.name.startswith("org.apache"): continue
@@ -581,26 +708,90 @@
verify_aidl(clazz)
verify_internal(clazz)
verify_layering(clazz)
- verify_boolean(clazz)
+ verify_boolean(clazz, api)
verify_collections(clazz)
verify_flags(clazz)
return failures
+def verify_compat(cur, prev):
+ """Find any incompatible API changes between two levels."""
+ global failures
+
+ def class_exists(api, test):
+ return test.fullname in api
+
+ def ctor_exists(api, clazz, test):
+ for m in clazz.ctors:
+ if m.ident == test.ident: return True
+ return False
+
+ def all_methods(api, clazz):
+ methods = list(clazz.methods)
+ if clazz.extends is not None:
+ methods.extend(all_methods(api, api[clazz.extends]))
+ return methods
+
+ def method_exists(api, clazz, test):
+ methods = all_methods(api, clazz)
+ for m in methods:
+ if m.ident == test.ident: return True
+ return False
+
+ def field_exists(api, clazz, test):
+ for f in clazz.fields:
+ if f.ident == test.ident: return True
+ return False
+
+ failures = {}
+ for key in sorted(prev.keys()):
+ prev_clazz = prev[key]
+
+ if not class_exists(cur, prev_clazz):
+ error(prev_clazz, None, "Class removed or incompatible change")
+ continue
+
+ cur_clazz = cur[key]
+
+ for test in prev_clazz.ctors:
+ if not ctor_exists(cur, cur_clazz, test):
+ error(prev_clazz, prev_ctor, "Constructor removed or incompatible change")
+
+ methods = all_methods(prev, prev_clazz)
+ for test in methods:
+ if not method_exists(cur, cur_clazz, test):
+ error(prev_clazz, test, "Method removed or incompatible change")
+
+ for test in prev_clazz.fields:
+ if not field_exists(cur, cur_clazz, test):
+ error(prev_clazz, test, "Field removed or incompatible change")
+
+ return failures
+
+
cur = parse_api(sys.argv[1])
-cur_fail = verify_all(cur)
+cur_fail = verify_style(cur)
if len(sys.argv) > 2:
prev = parse_api(sys.argv[2])
- prev_fail = verify_all(prev)
+ prev_fail = verify_style(prev)
# ignore errors from previous API level
for p in prev_fail:
if p in cur_fail:
- cur_fail.remove(p)
+ del cur_fail[p]
+
+ # look for compatibility issues
+ compat_fail = verify_compat(cur, prev)
+
+ print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
+ for f in sorted(compat_fail):
+ print compat_fail[f]
+ print
-for f in cur_fail:
- print f
+print "%s API style issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
+for f in sorted(cur_fail):
+ print cur_fail[f]
print
diff --git a/tools/layoutlib/.idea/codeStyleSettings.xml b/tools/layoutlib/.idea/codeStyleSettings.xml
index 33937b3..b324213 100644
--- a/tools/layoutlib/.idea/codeStyleSettings.xml
+++ b/tools/layoutlib/.idea/codeStyleSettings.xml
@@ -27,12 +27,12 @@
<package name="" withSubpackages="true" static="true" />
</value>
</option>
+ <option name="RIGHT_MARGIN" value="100" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
- <option name="RIGHT_MARGIN" value="100" />
<option name="WRAP_COMMENTS" value="true" />
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
diff --git a/tools/layoutlib/.idea/libraries/asm_4_0.xml b/tools/layoutlib/.idea/libraries/asm_4_0.xml
index 578a7bf..7df287f 100644
--- a/tools/layoutlib/.idea/libraries/asm_4_0.xml
+++ b/tools/layoutlib/.idea/libraries/asm_4_0.xml
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="asm-4.0">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/asm/asm-4.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/asm-4.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/asm/src.zip!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/src.zip!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/framework_jar.xml b/tools/layoutlib/.idea/libraries/framework_jar.xml
index 11f5b89..6695a36 100644
--- a/tools/layoutlib/.idea/libraries/framework_jar.xml
+++ b/tools/layoutlib/.idea/libraries/framework_jar.xml
@@ -1,13 +1,13 @@
<component name="libraryTable">
<library name="framework.jar">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="file://$ANDROID_BUILD_TOP$/frameworks/base/core/java" />
- <root url="file://$ANDROID_BUILD_TOP$/frameworks/base/graphics/java" />
- <root url="file://$ANDROID_BUILD_TOP$/libcore/luni/src/main/java" />
+ <root url="file://$PROJECT_DIR$/../../core/java" />
+ <root url="file://$PROJECT_DIR$/../../graphics/java" />
+ <root url="file://$PROJECT_DIR$/../../../../libcore/luni/src/main/java" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/guava.xml b/tools/layoutlib/.idea/libraries/guava.xml
index de5607e..d47fc06 100644
--- a/tools/layoutlib/.idea/libraries/guava.xml
+++ b/tools/layoutlib/.idea/libraries/guava.xml
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="guava">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="file://$ANDROID_BUILD_TOP$/external/guava/guava/src" />
+ <root url="file://$PROJECT_DIR$/../../../../external/guava/guava/src" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/icu4j.xml b/tools/layoutlib/.idea/libraries/icu4j.xml
index 8d9a318..dbe0bd7 100644
--- a/tools/layoutlib/.idea/libraries/icu4j.xml
+++ b/tools/layoutlib/.idea/libraries/icu4j.xml
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="icu4j">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/icu4j/icu4j.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/icu4j/icu4j.jar!/" />
</CLASSES>
<JAVADOC>
<root url="http://icu-project.org/apiref/icu4j50rc/" />
diff --git a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml b/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
index 91feaea..2a65050 100644
--- a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
+++ b/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="kxml2-2.3.0">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="file://$ANDROID_BUILD_TOP$/libcore/xml/src/main/java" />
+ <root url="file://$PROJECT_DIR$/../../../../libcore/xml/src/main/java" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml b/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
index be928da..5952002 100644
--- a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="layoutlib_api-prebuilt">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
diff --git a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml b/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
index 338137b..f34f7dd 100644
--- a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="ninepatch-prebuilt">
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
diff --git a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml b/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
index 6479886..b325ad4 100644
--- a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
+++ b/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
@@ -4,7 +4,7 @@
<root url="file://$PROJECT_DIR$" />
</ANNOTATIONS>
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
diff --git a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
index badbbab..f965ba7 100644
--- a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
+++ b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml
@@ -8,7 +8,7 @@
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
- <option name="VM_PARAMETERS" value="-ea -Dplatform.dir="$ANDROID_BUILD_TOP$/out/host/linux-x86/sdk/sdk/android-sdk_eng.deepanshu_linux-x86/platforms/android-L" -Dtest_res.dir="$PROJECT_DIR$/bridge/tests/res"" />
+ <option name="VM_PARAMETERS" value="-ea -Dtest_res.dir="$PROJECT_DIR$/bridge/tests/res"" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index e62925b..fb0b866 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -4,7 +4,7 @@
<option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
- <option name="WORKING_DIRECTORY" value="file://$ANDROID_BUILD_TOP$/" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<option name="ALTERNATIVE_JRE_PATH" value="1.6" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
diff --git a/tools/layoutlib/.idea/vcs.xml b/tools/layoutlib/.idea/vcs.xml
index 8114960..9ab281a 100644
--- a/tools/layoutlib/.idea/vcs.xml
+++ b/tools/layoutlib/.idea/vcs.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
- <mapping directory="$ANDROID_BUILD_TOP$/frameworks/base" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index 7553b59..0f96916 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -34,11 +34,11 @@
<orderEntry type="module-library" scope="TEST">
<library>
<CLASSES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/sdk-common/sdk-common.jar!/" />
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$ANDROID_BUILD_TOP$/prebuilts/misc/common/sdk-common/sdk-common-sources.jar!/" />
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common-sources.jar!/" />
</SOURCES>
</library>
</orderEntry>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 5b69681..aaba545 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -90,9 +90,16 @@
// fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
// first count the array size
int count = 0;
- for (ResourceValue data : mResourceData) {
- if (data != null && !RenderResources.REFERENCE_NULL.equals(data.getValue())) {
- count++;
+ for (int i = 0; i < mResourceData.length; i++) {
+ ResourceValue data = mResourceData[i];
+ if (data != null) {
+ if (RenderResources.REFERENCE_NULL.equals(data.getValue())) {
+ // No need to store this resource value. This saves needless checking for
+ // "@null" every time an attribute is requested.
+ mResourceData[i] = null;
+ } else {
+ count++;
+ }
}
}
@@ -103,8 +110,7 @@
// fill the array with the indices.
int index = 1;
for (int i = 0 ; i < mResourceData.length ; i++) {
- if (mResourceData[i] != null
- && !RenderResources.REFERENCE_NULL.equals(mResourceData[i].getValue())) {
+ if (mResourceData[i] != null) {
mIndices[index++] = i;
}
}
@@ -215,10 +221,6 @@
String s = mResourceData[index].getValue();
- if (RenderResources.REFERENCE_NULL.equals(s)) {
- return defValue;
- }
-
if (s == null || s.length() == 0) {
return defValue;
}
@@ -231,6 +233,20 @@
// Field is not null and is not an integer.
// Check for possible constants and try to find them.
+ return (int) resolveEnumAttribute(index, defValue);
+ }
+
+ /**
+ * Searches for the string in the attributes (flag or enums) and returns the integer.
+ * If found, it will return an integer matching the value. However, if the value is not found,
+ * it returns {@code defValue} which may be a float.
+ *
+ * @param index Index of attribute to retrieve.
+ * @param defValue Value to return if the attribute is not found.
+ *
+ * @return Attribute int value, or defValue if not defined.
+ */
+ private float resolveEnumAttribute(int index, float defValue) {
// Get the map of attribute-constant -> IntegerValue
Map<String, Integer> map = null;
if (mIsFramework[index]) {
@@ -249,7 +265,7 @@
int result = 0;
// split the value in case this is a mix of several flags.
- String[] keywords = s.split("\\|");
+ String[] keywords = mResourceData[index].getValue().split("\\|");
for (String keyword : keywords) {
Integer i = map.get(keyword.trim());
if (i != null) {
@@ -258,7 +274,7 @@
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
"\"%s\" in attribute \"%2$s\" is not a valid value",
- keyword, mNames[index]), null /*data*/);
+ keyword, mNames[index]), null);
}
}
return result;
@@ -293,7 +309,7 @@
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
"\"%s\" in attribute \"%2$s\" cannot be converted to float.",
- s, mNames[index]), null /*data*/);
+ s, mNames[index]), null);
// we'll return the default value below.
}
@@ -358,10 +374,6 @@
return null;
}
- if (RenderResources.REFERENCE_NULL.equals(value)) {
- return null;
- }
-
// let the framework inflate the ColorStateList from the XML file.
File f = new File(value);
if (f.isFile()) {
@@ -377,13 +389,13 @@
}
} catch (XmlPullParserException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null /*data*/);
+ "Failed to configure parser for " + value, e, null);
return null;
} catch (Exception e) {
// this is an error and not warning since the file existence is checked before
// attempting to parse it.
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null /*data*/);
+ "Failed to parse file " + value, e, null);
return null;
}
@@ -393,7 +405,7 @@
int color = ResourceHelper.getColor(value);
return ColorStateList.valueOf(color);
} catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null /*data*/);
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null);
}
return null;
@@ -443,26 +455,15 @@
if (s == null) {
return defValue;
- } else if (s.equals(BridgeConstants.MATCH_PARENT) ||
- s.equals(BridgeConstants.FILL_PARENT)) {
- return LayoutParams.MATCH_PARENT;
- } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
- return LayoutParams.WRAP_CONTENT;
- } else if (RenderResources.REFERENCE_NULL.equals(s)) {
- return defValue;
}
- if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
+ if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
return mValue.getDimension(mBridgeResources.getDisplayMetrics());
}
- // looks like we were unable to resolve the dimension value
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format(
- "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
- s, mNames[index]), null /*data*/);
-
- return defValue;
+ // looks like we were unable to resolve the dimension value. Check if it is an attribute
+ // constant.
+ return resolveEnumAttribute(index, defValue);
}
/**
@@ -518,7 +519,7 @@
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
"\"%1$s\" in attribute \"%2$s\" is not a valid format.",
- s, mNames[index]), null /*data*/);
+ s, mNames[index]), null);
}
}
@@ -575,11 +576,9 @@
return LayoutParams.MATCH_PARENT;
} else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
return LayoutParams.WRAP_CONTENT;
- } else if (RenderResources.REFERENCE_NULL.equals(s)) {
- throw new RuntimeException();
}
- if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
+ if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
final int res = (int)(f+0.5f);
@@ -621,16 +620,15 @@
return defValue;
}
- if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue,
- false /*requireUnit*/)) {
+ if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) {
return mValue.getFraction(base, pbase);
}
// looks like we were unable to resolve the fraction value
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
- "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
- value, mNames[index]), null /*data*/);
+ "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
+ value, mNames[index]), null);
return defValue;
}
@@ -669,10 +667,6 @@
return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
}
- if (RenderResources.REFERENCE_NULL.equals(resValue.getValue())) {
- return defValue;
- }
-
// if the attribute was a reference to a resource, and not a declaration of an id (@+id),
// then the xml attribute value was "resolved" which leads us to a ResourceValue with a
// valid getType() and getName() returning a resource name.
@@ -782,7 +776,7 @@
ResourceValue value = mResourceData[index];
String stringValue = value.getValue();
- if (stringValue == null || RenderResources.REFERENCE_NULL.equals(stringValue)) {
+ if (stringValue == null) {
return null;
}
@@ -812,18 +806,9 @@
String value = mResourceData[index].getValue();
if (value != null) {
- if (RenderResources.REFERENCE_NULL.equals(value)) {
- return null;
- }
-
return new CharSequence[] { value };
}
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format(
- String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
- index, mResourceData[index].getName())), null /*data*/);
-
return null;
}
@@ -862,8 +847,7 @@
String s = mResourceData[index].getValue();
- return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue,
- false /*requireUnit*/);
+ return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
}
/**
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 2604e97..c403ce6 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -222,7 +222,8 @@
@Override
public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
- int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
+ boolean scaleUp) {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index adb0937..99ae7c9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -63,11 +63,11 @@
* Returns the color value represented by the given string value
* @param value the color value
* @return the color as an int
- * @throw NumberFormatException if the conversion failed.
+ * @throws NumberFormatException if the conversion failed.
*/
public static int getColor(String value) {
if (value != null) {
- if (value.startsWith("#") == false) {
+ if (!value.startsWith("#")) {
throw new NumberFormatException(
String.format("Color value '%s' must start with #", value));
}
@@ -113,7 +113,7 @@
public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
String value = resValue.getValue();
- if (value != null && RenderResources.REFERENCE_NULL.equals(value) == false) {
+ if (value != null && !RenderResources.REFERENCE_NULL.equals(value)) {
// first check if the value is a file (xml most likely)
File f = new File(value);
if (f.isFile()) {
@@ -360,7 +360,7 @@
*/
public static boolean parseFloatAttribute(String attribute, String value,
TypedValue outValue, boolean requireUnit) {
- assert requireUnit == false || attribute != null;
+ assert !requireUnit || attribute != null;
// remove the space before and after
value = value.trim();
@@ -379,7 +379,7 @@
}
// check the first character
- if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') {
+ if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') {
return false;
}
@@ -411,7 +411,7 @@
if (end.length() == 0) {
if (outValue != null) {
- if (requireUnit == false) {
+ if (!requireUnit) {
outValue.type = TypedValue.TYPE_FLOAT;
outValue.data = Float.floatToIntBits(f);
} else {
@@ -489,6 +489,8 @@
private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) {
outValue.type = unit.type;
+ // COMPLEX_UNIT_SHIFT is 0 and hence intelliJ complains about it. Suppress the warning.
+ //noinspection PointlessBitwiseExpression
outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT;
outScale[0] = unit.scale;
}
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 7a9e067..5e47c8c 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -34,5 +34,8 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# Copy the jar to DIST_DIR for sdk builds
+$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
+
# Build all sub-directories
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 31b3e25..a2588a6 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -104,9 +104,61 @@
return platformDir;
}
// System Property not set. Try to find the directory in the build directory.
- String out = System.getenv("ANDROID_HOST_OUT");
- if (out == null || out.isEmpty() || !new File(out).isDirectory()) {
- // Can't find the out directory.
+ String androidHostOut = System.getenv("ANDROID_HOST_OUT");
+ if (androidHostOut != null) {
+ platformDir = getPlatformDirFromHostOut(new File(androidHostOut));
+ if (platformDir != null) {
+ return platformDir;
+ }
+ }
+ String workingDirString = System.getProperty("user.dir");
+ File workingDir = new File(workingDirString);
+ // Test if workingDir is android checkout root.
+ platformDir = getPlatformDirFromRoot(workingDir);
+ if (platformDir != null) {
+ return platformDir;
+ }
+ // Test if workingDir is platform/frameworks/base/tools/layoutlib. That is, root should be
+ // workingDir/../../../../ (4 levels up)
+ File currentDir = workingDir;
+ for (int i = 0; i < 4; i++) {
+ if (currentDir != null) {
+ currentDir = currentDir.getParentFile();
+ }
+ }
+ return currentDir == null ? null : getPlatformDirFromRoot(currentDir);
+ }
+
+ private static String getPlatformDirFromRoot(File root) {
+ if (!root.isDirectory()) {
+ return null;
+ }
+ File out = new File(root, "out");
+ if (!out.isDirectory()) {
+ return null;
+ }
+ File host = new File(out, "host");
+ if (!host.isDirectory()) {
+ return null;
+ }
+ File[] hosts = host.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File path) {
+ return path.isDirectory() && (path.getName().startsWith("linux-") || path.getName()
+ .startsWith("darwin-"));
+ }
+ });
+ for (File hostOut : hosts) {
+ String platformDir = getPlatformDirFromHostOut(hostOut);
+ if (platformDir != null) {
+ return platformDir;
+ }
+ }
+ return null;
+ }
+
+ private static String getPlatformDirFromHostOut(File out) {
+ if (!out.isDirectory()) {
return null;
}
File sdkDir = new File(out, "sdk" + File.separator + "sdk");
@@ -117,7 +169,7 @@
File[] possibleSdks = sdkDir.listFiles(new FileFilter() {
@Override
public boolean accept(File path) {
- return path.isDirectory() && path.getAbsolutePath().contains("android-sdk");
+ return path.isDirectory() && path.getName().contains("android-sdk");
}
});
for (File possibleSdk : possibleSdks) {
diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk
index 9bd48ab..e6f0bc3 100644
--- a/tools/layoutlib/create/Android.mk
+++ b/tools/layoutlib/create/Android.mk
@@ -26,3 +26,6 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk
new file mode 100644
index 0000000..c197d57
--- /dev/null
+++ b/tools/layoutlib/create/tests/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-java-files-under, com)
+
+LOCAL_JAVA_RESOURCE_DIRS := data mock_data
+
+LOCAL_MODULE := layoutlib-create-tests
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := layoutlib_create junit
+LOCAL_STATIC_JAVA_LIBRARIES := asm-4.0
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Copy the jar to DIST_DIR for sdk builds
+$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/wifi/java/android/net/wifi/IWifiScanner.aidl b/wifi/java/android/net/wifi/IWifiScanner.aidl
index fef2d11..3984934 100644
--- a/wifi/java/android/net/wifi/IWifiScanner.aidl
+++ b/wifi/java/android/net/wifi/IWifiScanner.aidl
@@ -17,6 +17,7 @@
package android.net.wifi;
import android.os.Messenger;
+import android.os.Bundle;
/**
* {@hide}
@@ -24,4 +25,6 @@
interface IWifiScanner
{
Messenger getMessenger();
+
+ Bundle getAvailableChannels(int band);
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ac2a176..21f200f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -341,6 +341,12 @@
/**
* @hide
+ * last time we connected, this configuration had no internet access
+ */
+ public boolean noInternetAccess;
+
+ /**
+ * @hide
* Uid of app creating the configuration
*/
@SystemApi
@@ -673,6 +679,49 @@
@SystemApi
public int numAssociation;
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration with Low RSSI.
+ */
+ public int numUserTriggeredWifiDisableLowRSSI;
+
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration with Bad RSSI.
+ */
+ public int numUserTriggeredWifiDisableBadRSSI;
+
+ /**
+ * @hide
+ * Number of time user disabled WiFi while associated to this configuration
+ * and RSSI was not HIGH.
+ */
+ public int numUserTriggeredWifiDisableNotHighRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration with Low RSSI.
+ */
+ public int numTicksAtLowRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration with Bad RSSI.
+ */
+ public int numTicksAtBadRSSI;
+
+ /**
+ * @hide
+ * Number of ticks associated to this configuration
+ * and RSSI was not HIGH.
+ */
+ public int numTicksAtNotHighRSSI;
+ /**
+ * @hide
+ * Number of time user (WifiManager) triggered association to this configuration.
+ * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps
+ */
+ public int numUserTriggeredJoinAttempts;
/**
* @hide
@@ -725,6 +774,7 @@
selfAdded = false;
didSelfAdd = false;
ephemeral = false;
+ noInternetAccess = false;
mIpConfiguration = new IpConfiguration();
}
@@ -824,8 +874,10 @@
sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
}
if (this.didSelfAdd || this.selfAdded) {
- if (this.didSelfAdd) sbuf.append(" didSelfAdd ");
- if (this.selfAdded) sbuf.append(" selfAdded ");
+ if (this.didSelfAdd) sbuf.append(" didSelfAdd");
+ if (this.selfAdded) sbuf.append(" selfAdded");
+ if (this.noInternetAccess) sbuf.append(" noInternetAccess");
+
sbuf.append("\n");
}
sbuf.append(" KeyMgmt:");
@@ -896,18 +948,44 @@
sbuf.append(mIpConfiguration.toString());
- if (selfAdded) sbuf.append("selfAdded");
- if (creatorUid != 0) sbuf.append("uid=" + Integer.toString(creatorUid));
+ if (this.creatorUid != 0) sbuf.append("uid=" + Integer.toString(creatorUid));
- if (blackListTimestamp != 0) {
+ if (this.blackListTimestamp != 0) {
long now_ms = System.currentTimeMillis();
- long diff = now_ms - blackListTimestamp;
+ long diff = now_ms - this.blackListTimestamp;
if (diff <= 0) {
sbuf.append("blackListed since <incorrect>");
} else {
sbuf.append("blackListed since ").append(Long.toString(diff/1000)).append( "sec");
}
}
+ sbuf.append('\n');
+ if (this.linkedConfigurations != null) {
+ for(String key : this.linkedConfigurations.keySet()) {
+ sbuf.append(" linked: ").append(key);
+ sbuf.append('\n');
+ }
+ }
+ if (this.connectChoices != null) {
+ for(String key : this.connectChoices.keySet()) {
+ Integer choice = this.connectChoices.get(key);
+ if (choice != null) {
+ sbuf.append(" choice: ").append(key);
+ sbuf.append(" = ").append(choice);
+ sbuf.append('\n');
+ }
+ }
+ }
+ sbuf.append(" triggeredLow: ").append(numUserTriggeredWifiDisableLowRSSI);
+ sbuf.append(" triggeredBad: ").append(numUserTriggeredWifiDisableBadRSSI);
+ sbuf.append(" triggeredNotHigh: ").append(numUserTriggeredWifiDisableNotHighRSSI);
+ sbuf.append('\n');
+ sbuf.append(" ticksLow: ").append(numTicksAtLowRSSI);
+ sbuf.append(" ticksBad: ").append(numTicksAtBadRSSI);
+ sbuf.append(" ticksNotHigh: ").append(numTicksAtNotHighRSSI);
+ sbuf.append('\n');
+ sbuf.append(" triggeredJoin: ").append(numUserTriggeredJoinAttempts);
+ sbuf.append('\n');
return sbuf.toString();
}
@@ -1197,7 +1275,7 @@
mCachedConfigKey = null; //force null configKey
autoJoinStatus = source.autoJoinStatus;
selfAdded = source.selfAdded;
-
+ noInternetAccess = source.noInternetAccess;
if (source.visibility != null) {
visibility = new Visibility(source.visibility);
}
@@ -1217,6 +1295,13 @@
numScorerOverride = source.numScorerOverride;
numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
numAssociation = source.numAssociation;
+ numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI;
+ numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI;
+ numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI;
+ numTicksAtLowRSSI = source.numTicksAtLowRSSI;
+ numTicksAtBadRSSI = source.numTicksAtBadRSSI;
+ numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI;
+ numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts;
}
}
@@ -1259,6 +1344,7 @@
dest.writeInt(autoJoinStatus);
dest.writeInt(selfAdded ? 1 : 0);
dest.writeInt(didSelfAdd ? 1 : 0);
+ dest.writeInt(noInternetAccess ? 1 : 0);
dest.writeInt(creatorUid);
dest.writeInt(lastConnectUid);
dest.writeInt(lastUpdateUid);
@@ -1269,6 +1355,14 @@
dest.writeInt(numScorerOverride);
dest.writeInt(numScorerOverrideAndSwitchedNetwork);
dest.writeInt(numAssociation);
+ dest.writeInt(numUserTriggeredWifiDisableLowRSSI);
+ dest.writeInt(numUserTriggeredWifiDisableBadRSSI);
+ dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI);
+ dest.writeInt(numTicksAtLowRSSI);
+ dest.writeInt(numTicksAtBadRSSI);
+ dest.writeInt(numTicksAtNotHighRSSI);
+ dest.writeInt(numUserTriggeredJoinAttempts);
+
}
/** Implement the Parcelable interface {@hide} */
@@ -1307,6 +1401,7 @@
config.autoJoinStatus = in.readInt();
config.selfAdded = in.readInt() != 0;
config.didSelfAdd = in.readInt() != 0;
+ config.noInternetAccess = in.readInt() != 0;
config.creatorUid = in.readInt();
config.lastConnectUid = in.readInt();
config.lastUpdateUid = in.readInt();
@@ -1317,6 +1412,13 @@
config.numScorerOverride = in.readInt();
config.numScorerOverrideAndSwitchedNetwork = in.readInt();
config.numAssociation = in.readInt();
+ config.numUserTriggeredWifiDisableLowRSSI = in.readInt();
+ config.numUserTriggeredWifiDisableBadRSSI = in.readInt();
+ config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt();
+ config.numTicksAtLowRSSI = in.readInt();
+ config.numTicksAtBadRSSI = in.readInt();
+ config.numTicksAtNotHighRSSI = in.readInt();
+ config.numUserTriggeredJoinAttempts = in.readInt();
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 74f2f65..1393bce 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1000,6 +1000,7 @@
}
/** @hide */
+ @SystemApi
public boolean startScan(WorkSource workSource) {
try {
mService.startScan(null, workSource);
@@ -1073,6 +1074,7 @@
* @return false if not supported.
* @hide
*/
+ @SystemApi
public boolean isBatchedScanSupported() {
try {
return mService.isBatchedScanSupported();
@@ -1099,6 +1101,7 @@
* {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
* @hide
*/
+ @SystemApi
public List<BatchedScanResult> getBatchedScanResults() {
try {
return mService.getBatchedScanResults(mContext.getOpPackageName());
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index e7bcb23..65c00bd 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.content.Context;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -76,6 +77,9 @@
/** Invalid request */
public static final int REASON_INVALID_REQUEST = -3;
+ /** @hide */
+ public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";
+
/**
* Generic action callback invocation interface
* @hide
@@ -92,7 +96,12 @@
* @hide
*/
public List<Integer> getAvailableChannels(int band) {
- return null;
+ try {
+ Bundle bundle = mService.getAvailableChannels(band);
+ return bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
+ } catch (RemoteException e) {
+ return null;
+ }
}
/**