diff options
527 files changed, 4579 insertions, 1957 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index c5c7fe3302cc..758273b78f7e 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -182,6 +182,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/usr/keychars/frameworks) $(call add-clean-step, rm -f $(PRODUCT_OUT)/system/media/video/*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/effects/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/framework-res_intermediates) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/api/current.txt b/api/current.txt index a3e6fbcbd1fa..dc21e90a5c89 100644 --- a/api/current.txt +++ b/api/current.txt @@ -20,13 +20,10 @@ package android { field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS"; field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE"; field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET"; - field public static final java.lang.String BIND_CALL_SERVICE = "android.permission.BIND_CALL_SERVICE"; field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN"; field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD"; - field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE"; field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"; field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE"; - field public static final java.lang.String BIND_PRINT_SPOOLER_SERVICE = "android.permission.BIND_PRINT_SPOOLER_SERVICE"; field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS"; field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE"; field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE"; @@ -79,7 +76,6 @@ package android { field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE"; field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS"; field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS"; - field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS"; field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS"; field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR"; field public static final java.lang.String MEDIA_CONTENT_CONTROL = "android.permission.MEDIA_CONTENT_CONTROL"; @@ -4368,6 +4364,8 @@ package android.app { method public void clear() throws java.io.IOException; method public void clearWallpaperOffsets(android.os.IBinder); method public void forgetLoadedWallpaper(); + method public android.graphics.drawable.Drawable getBuiltInDrawable(); + method public android.graphics.drawable.Drawable getBuiltInDrawable(int, int, boolean, float, float); method public android.content.Intent getCropAndSetWallpaperIntent(android.net.Uri); method public int getDesiredMinimumHeight(); method public int getDesiredMinimumWidth(); @@ -5759,6 +5757,7 @@ package android.content { method public static java.util.List<android.content.SyncInfo> getCurrentSyncs(); method public static int getIsSyncable(android.accounts.Account, java.lang.String); method public static boolean getMasterSyncAutomatically(); + method public java.util.List<android.content.UriPermission> getOutgoingPersistedUriPermissions(); method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.accounts.Account, java.lang.String); method public java.util.List<android.content.UriPermission> getPersistedUriPermissions(); method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String); @@ -7255,6 +7254,7 @@ package android.content.pm { method public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int); method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int); method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int); + method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int); method public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int); method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract deprecated void removePackageFromPreferred(java.lang.String); @@ -7420,6 +7420,7 @@ package android.content.pm { ctor public ProviderInfo(); ctor public ProviderInfo(android.content.pm.ProviderInfo); method public int describeContents(); + method public void dump(android.util.Printer, java.lang.String); field public static final android.os.Parcelable.Creator CREATOR; field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public java.lang.String authority; @@ -7453,6 +7454,7 @@ package android.content.pm { field public java.lang.CharSequence nonLocalizedLabel; field public int preferredOrder; field public int priority; + field public android.content.pm.ProviderInfo providerInfo; field public java.lang.String resolvePackageName; field public android.content.pm.ServiceInfo serviceInfo; field public int specificIndex; @@ -20982,6 +20984,7 @@ package android.provider { field public static final java.lang.String EXTRA_ERROR = "error"; field public static final java.lang.String EXTRA_INFO = "info"; field public static final java.lang.String EXTRA_LOADING = "loading"; + field public static final java.lang.String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER"; } public static final class DocumentsContract.Document { @@ -24477,6 +24480,7 @@ package android.test.mock { method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int); method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(android.content.Intent, int); method public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(android.content.ComponentName, android.content.Intent[], android.content.Intent, int); + method public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.Intent, int); method public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(android.content.Intent, int); method public java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public void removePackageFromPreferred(java.lang.String); @@ -28392,6 +28396,7 @@ package android.view { field public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4; // 0x4 field public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2; // 0x2 field public static final int SYSTEM_UI_FLAG_IMMERSIVE = 2048; // 0x800 + field public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096; // 0x1000 field public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024; // 0x400 field public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512; // 0x200 field public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256; // 0x100 @@ -29280,6 +29285,7 @@ package android.view.accessibility { public final class AccessibilityManager { method public boolean addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); + method public boolean addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList(); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int); method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList(); @@ -29287,6 +29293,7 @@ package android.view.accessibility { method public boolean isEnabled(); method public boolean isTouchExplorationEnabled(); method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener); + method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener); method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent); } @@ -29294,6 +29301,10 @@ package android.view.accessibility { method public abstract void onAccessibilityStateChanged(boolean); } + public static abstract interface AccessibilityManager.TouchExplorationStateChangeListener { + method public abstract void onTouchExplorationStateChanged(boolean); + } + public class AccessibilityNodeInfo implements android.os.Parcelable { method public void addAction(int); method public void addChild(android.view.View); diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index d8f9e493692d..188408d04d94 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -191,13 +191,25 @@ public class LayoutTransition { private long mChangingStagger = 0; /** + * Static interpolators - these are stateless and can be shared across the instances + */ + private static TimeInterpolator ACCEL_DECEL_INTERPOLATOR = + new AccelerateDecelerateInterpolator(); + private static TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator(); + private static TimeInterpolator sAppearingInterpolator = ACCEL_DECEL_INTERPOLATOR; + private static TimeInterpolator sDisappearingInterpolator = ACCEL_DECEL_INTERPOLATOR; + private static TimeInterpolator sChangingAppearingInterpolator = DECEL_INTERPOLATOR; + private static TimeInterpolator sChangingDisappearingInterpolator = DECEL_INTERPOLATOR; + private static TimeInterpolator sChangingInterpolator = DECEL_INTERPOLATOR; + + /** * The default interpolators used for the animations */ - private TimeInterpolator mAppearingInterpolator = new AccelerateDecelerateInterpolator(); - private TimeInterpolator mDisappearingInterpolator = new AccelerateDecelerateInterpolator(); - private TimeInterpolator mChangingAppearingInterpolator = new DecelerateInterpolator(); - private TimeInterpolator mChangingDisappearingInterpolator = new DecelerateInterpolator(); - private TimeInterpolator mChangingInterpolator = new DecelerateInterpolator(); + private TimeInterpolator mAppearingInterpolator = sAppearingInterpolator; + private TimeInterpolator mDisappearingInterpolator = sDisappearingInterpolator; + private TimeInterpolator mChangingAppearingInterpolator = sChangingAppearingInterpolator; + private TimeInterpolator mChangingDisappearingInterpolator = sChangingDisappearingInterpolator; + private TimeInterpolator mChangingInterpolator = sChangingInterpolator; /** * These hashmaps are used to store the animations that are currently running as part of @@ -905,14 +917,24 @@ public class LayoutTransition { case APPEARING: startDelay = mChangingAppearingDelay + staggerDelay; staggerDelay += mChangingAppearingStagger; + if (mChangingAppearingInterpolator != sChangingAppearingInterpolator) { + anim.setInterpolator(mChangingAppearingInterpolator); + } break; case DISAPPEARING: startDelay = mChangingDisappearingDelay + staggerDelay; staggerDelay += mChangingDisappearingStagger; + if (mChangingDisappearingInterpolator != + sChangingDisappearingInterpolator) { + anim.setInterpolator(mChangingDisappearingInterpolator); + } break; case CHANGING: startDelay = mChangingDelay + staggerDelay; staggerDelay += mChangingStagger; + if (mChangingInterpolator != sChangingInterpolator) { + anim.setInterpolator(mChangingInterpolator); + } break; } anim.setStartDelay(startDelay); @@ -1148,6 +1170,9 @@ public class LayoutTransition { anim.setTarget(child); anim.setStartDelay(mAppearingDelay); anim.setDuration(mAppearingDuration); + if (mAppearingInterpolator != sAppearingInterpolator) { + anim.setInterpolator(mAppearingInterpolator); + } if (anim instanceof ObjectAnimator) { ((ObjectAnimator) anim).setCurrentPlayTime(0); } @@ -1192,6 +1217,9 @@ public class LayoutTransition { Animator anim = mDisappearingAnim.clone(); anim.setStartDelay(mDisappearingDelay); anim.setDuration(mDisappearingDuration); + if (mDisappearingInterpolator != sDisappearingInterpolator) { + anim.setInterpolator(mDisappearingInterpolator); + } anim.setTarget(child); final float preAnimAlpha = child.getAlpha(); anim.addListener(new AnimatorListenerAdapter() { diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index a38fbbfbac3c..e29f8ea63647 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1455,12 +1455,14 @@ public class Activity extends ContextThemeWrapper } /** - * Report to the system that your app is now fully drawn. This is only used - * to help instrument app launch times, so that the app can report when it is - * fully in a usable state; without this, all the system can determine is when - * its window is first drawn and displayed. To participate in app launch time + * Report to the system that your app is now fully drawn, purely for diagnostic + * purposes (calling it does not impact the visible behavior of the activity). + * This is only used to help instrument application launch times, so that the + * app can report when it is fully in a usable state; without this, the only thing + * the system itself can determine is the point at which the activity's window + * is <em>first</em> drawn and displayed. To participate in app launch time * measurement, you should always call this method after first launch (when - * {@link #onCreate(android.os.Bundle)} is called) at the point where you have + * {@link #onCreate(android.os.Bundle)} is called), at the point where you have * entirely drawn your UI and populated with all of the significant data. You * can safely call this method any time after first launch as well, in which case * it will simply be ignored. diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 1e65098faaaf..1067eb1b2add 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1463,7 +1463,10 @@ public class ActivityManager { /** * Permits an application to erase its own data from disk. This is equivalent to - * the user choosing to clear the app's data from within the device settings UI. + * the user choosing to clear the app's data from within the device settings UI. It + * erases all dynamic data associated with the app -- its private data and data in its + * private area on external storage -- but does not remove the installed application + * itself, nor any OBB files. * * @return {@code true} if the application successfully requested that the application's * data be erased; {@code false} otherwise. @@ -2253,7 +2256,9 @@ public class ActivityManager { * not be done on a UI thread. The data will be written to the given file * descriptor as text. An application must hold the * {@link android.Manifest.permission#DUMP} permission to make this call. - * @param fd The file descriptor that the dump should be written to. + * @param fd The file descriptor that the dump should be written to. The file + * descriptor is <em>not</em> closed by this function; the caller continues to + * own it. * @param packageName The name of the package that is to be dumped. */ public void dumpPackageState(FileDescriptor fd, String packageName) { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 961ee5768b94..74266ccf58a2 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1160,7 +1160,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case GET_PERSISTED_URI_PERMISSIONS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - final ParceledListSlice<UriPermission> perms = getPersistedUriPermissions(); + final String packageName = data.readString(); + final boolean incoming = data.readInt() != 0; + final ParceledListSlice<UriPermission> perms = getPersistedUriPermissions( + packageName, incoming); reply.writeNoException(); perms.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); return true; @@ -3500,10 +3503,13 @@ class ActivityManagerProxy implements IActivityManager } @Override - public ParceledListSlice<UriPermission> getPersistedUriPermissions() throws RemoteException { + public ParceledListSlice<UriPermission> getPersistedUriPermissions( + String packageName, boolean incoming) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + data.writeInt(incoming ? 1 : 0); mRemote.transact(GET_PERSISTED_URI_PERMISSIONS_TRANSACTION, data, reply, 0); reply.readException(); final ParceledListSlice<UriPermission> perms = ParceledListSlice.CREATOR.createFromParcel( diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b364af7bded8..df63ab342dfe 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -95,6 +95,7 @@ import com.android.internal.os.SamplingProfilerIntegration; import com.android.internal.util.FastPrintWriter; import com.android.internal.util.Objects; import com.android.org.conscrypt.OpenSSLSocketImpl; +import com.google.android.collect.Lists; import java.io.File; import java.io.FileDescriptor; @@ -1277,6 +1278,11 @@ public final class ActivityThread { } } } + + @Override + public void scheduleInstallProvider(ProviderInfo provider) { + queueOrSendMessage(H.INSTALL_PROVIDER, provider); + } } private class H extends Handler { @@ -1325,6 +1331,7 @@ public final class ActivityThread { public static final int UNSTABLE_PROVIDER_DIED = 142; public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; + public static final int INSTALL_PROVIDER = 145; String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { @@ -1373,6 +1380,7 @@ public final class ActivityThread { case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED"; case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS"; case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE"; + case INSTALL_PROVIDER: return "INSTALL_PROVIDER"; } } return Integer.toString(code); @@ -1590,6 +1598,9 @@ public final class ActivityThread { case TRANSLUCENT_CONVERSION_COMPLETE: handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1); break; + case INSTALL_PROVIDER: + handleInstallProvider((ProviderInfo) msg.obj); + break; } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); } @@ -2330,6 +2341,10 @@ public final class ActivityThread { } } + public void handleInstallProvider(ProviderInfo info) { + installContentProviders(mInitialApplication, Lists.newArrayList(info)); + } + private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>(); /** @@ -4636,15 +4651,14 @@ public final class ActivityThread { if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider " + provider + " " + prc.holder.info.name); mProviderRefCountMap.remove(provider); - if (prc.client != null && prc.client.mNames != null) { - for (String name : prc.client.mNames) { - ProviderClientRecord pr = mProviderMap.get(name); - if (pr != null && pr.mProvider.asBinder() == provider) { - Slog.i(TAG, "Removing dead content provider: " + name); - mProviderMap.remove(name); - } + for (int i=mProviderMap.size()-1; i>=0; i--) { + ProviderClientRecord pr = mProviderMap.valueAt(i); + if (pr != null && pr.mProvider.asBinder() == provider) { + Slog.i(TAG, "Removing dead content provider:" + pr.mProvider.toString()); + mProviderMap.removeAt(i); } } + if (fromClient) { // We found out about this due to execution in our client // code. Tell the activity manager about it now, to ensure diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 55c66726c387..b505d4f8e878 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -585,6 +585,22 @@ final class ApplicationPackageManager extends PackageManager { } @Override + public List<ResolveInfo> queryIntentContentProvidersAsUser( + Intent intent, int flags, int userId) { + try { + return mPM.queryIntentContentProviders(intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId); + } catch (RemoteException e) { + throw new RuntimeException("Package manager has died", e); + } + } + + @Override + public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { + return queryIntentContentProvidersAsUser(intent, flags, mContext.getUserId()); + } + + @Override public ProviderInfo resolveContentProvider(String name, int flags) { try { diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index e40a04b41ec0..347d43f63a69 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -618,6 +618,15 @@ public abstract class ApplicationThreadNative extends Binder reply.writeNoException(); return true; } + + case SCHEDULE_INSTALL_PROVIDER_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + ProviderInfo provider = ProviderInfo.CREATOR.createFromParcel(data); + scheduleInstallProvider(provider); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -1248,4 +1257,13 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(SET_PROCESS_STATE_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } + + @Override + public void scheduleInstallProvider(ProviderInfo provider) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + provider.writeToParcel(data, 0); + mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index dfea73671dc3..77c2ea0c1694 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -215,7 +215,8 @@ public interface IActivityManager extends IInterface { int mode) throws RemoteException; public void takePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException; public void releasePersistableUriPermission(Uri uri, int modeFlags) throws RemoteException; - public ParceledListSlice<UriPermission> getPersistedUriPermissions() throws RemoteException; + public ParceledListSlice<UriPermission> getPersistedUriPermissions( + String packageName, boolean incoming) throws RemoteException; public void showWaitingForDebugger(IApplicationThread who, boolean waiting) throws RemoteException; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 43a5fbdc8875..d0cc1bbc9c2b 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -137,6 +137,7 @@ public interface IApplicationThread extends IInterface { void scheduleTranslucentConversionComplete(IBinder token, boolean timeout) throws RemoteException; void setProcessState(int state) throws RemoteException; + void scheduleInstallProvider(ProviderInfo provider) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -189,4 +190,5 @@ public interface IApplicationThread extends IInterface { int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47; int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48; int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49; + int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50; } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 2bc7cbf8ec26..c39415f3c2d8 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -16,7 +16,6 @@ package android.app; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -24,13 +23,16 @@ import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.BitmapRegionDecoder; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -47,6 +49,7 @@ import android.util.Log; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -367,7 +370,7 @@ public class WallpaperManager { /** * Retrieve the current system wallpaper; if - * no wallpaper is set, the system default wallpaper is returned. + * no wallpaper is set, the system built-in static wallpaper is returned. * This is returned as an * abstract Drawable that you can install in a View to display whatever * wallpaper the user has currently set. @@ -385,6 +388,178 @@ public class WallpaperManager { } /** + * Returns a drawable for the system built-in static wallpaper . + * + */ + public Drawable getBuiltInDrawable() { + return getBuiltInDrawable(0, 0, false, 0, 0); + } + + /** + * Returns a drawable for the system built-in static wallpaper. Based on the parameters, the + * drawable can be cropped and scaled + * + * @param outWidth The width of the returned drawable + * @param outWidth The height of the returned drawable + * @param scaleToFit If true, scale the wallpaper down rather than just cropping it + * @param horizontalAlignment A float value between 0 and 1 specifying where to crop the image; + * 0 for left-aligned, 0.5 for horizontal center-aligned, and 1 for right-aligned + * @param verticalAlignment A float value between 0 and 1 specifying where to crop the image; + * 0 for top-aligned, 0.5 for vertical center-aligned, and 1 for bottom-aligned + * + */ + public Drawable getBuiltInDrawable(int outWidth, int outHeight, + boolean scaleToFit, float horizontalAlignment, float verticalAlignment) { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + return null; + } + Resources resources = mContext.getResources(); + horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment)); + verticalAlignment = Math.max(0, Math.min(1, verticalAlignment)); + + InputStream is = new BufferedInputStream( + resources.openRawResource(com.android.internal.R.drawable.default_wallpaper)); + + if (is == null) { + Log.e(TAG, "default wallpaper input stream is null"); + return null; + } else { + if (outWidth <= 0 || outHeight <= 0) { + Bitmap fullSize = BitmapFactory.decodeStream(is, null, null); + return new BitmapDrawable(resources, fullSize); + } else { + int inWidth; + int inHeight; + { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeStream(is, null, options); + if (options.outWidth != 0 && options.outHeight != 0) { + inWidth = options.outWidth; + inHeight = options.outHeight; + } else { + Log.e(TAG, "default wallpaper dimensions are 0"); + return null; + } + } + + is = new BufferedInputStream(resources.openRawResource( + com.android.internal.R.drawable.default_wallpaper)); + + RectF cropRectF; + + outWidth = Math.min(inWidth, outWidth); + outHeight = Math.min(inHeight, outHeight); + if (scaleToFit) { + cropRectF = getMaxCropRect(inWidth, inHeight, outWidth, outHeight, + horizontalAlignment, verticalAlignment); + } else { + float left = (inWidth - outWidth) * horizontalAlignment; + float right = left + outWidth; + float top = (inHeight - outHeight) * verticalAlignment; + float bottom = top + outHeight; + cropRectF = new RectF(bottom, left, right, top); + } + Rect roundedTrueCrop = new Rect(); + cropRectF.roundOut(roundedTrueCrop); + + if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { + Log.w(TAG, "crop has bad values for full size image"); + return null; + } + + // See how much we're reducing the size of the image + int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / outWidth, + roundedTrueCrop.height() / outHeight); + + // Attempt to open a region decoder + BitmapRegionDecoder decoder = null; + try { + decoder = BitmapRegionDecoder.newInstance(is, true); + } catch (IOException e) { + Log.w(TAG, "cannot open region decoder for default wallpaper"); + } + + Bitmap crop = null; + if (decoder != null) { + // Do region decoding to get crop bitmap + BitmapFactory.Options options = new BitmapFactory.Options(); + if (scaleDownSampleSize > 1) { + options.inSampleSize = scaleDownSampleSize; + } + crop = decoder.decodeRegion(roundedTrueCrop, options); + decoder.recycle(); + } + + if (crop == null) { + // BitmapRegionDecoder has failed, try to crop in-memory + is = new BufferedInputStream(resources.openRawResource( + com.android.internal.R.drawable.default_wallpaper)); + Bitmap fullSize = null; + if (is != null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + if (scaleDownSampleSize > 1) { + options.inSampleSize = scaleDownSampleSize; + } + fullSize = BitmapFactory.decodeStream(is, null, options); + } + if (fullSize != null) { + crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, + roundedTrueCrop.top, roundedTrueCrop.width(), + roundedTrueCrop.height()); + } + } + + if (crop == null) { + Log.w(TAG, "cannot decode default wallpaper"); + return null; + } + + // Scale down if necessary + if (outWidth > 0 && outHeight > 0 && + (crop.getWidth() != outWidth || crop.getHeight() != outHeight)) { + Matrix m = new Matrix(); + RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight()); + RectF returnRect = new RectF(0, 0, outWidth, outHeight); + m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); + Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), + (int) returnRect.height(), Bitmap.Config.ARGB_8888); + if (tmp != null) { + Canvas c = new Canvas(tmp); + Paint p = new Paint(); + p.setFilterBitmap(true); + c.drawBitmap(crop, m, p); + crop = tmp; + } + } + + return new BitmapDrawable(resources, crop); + } + } + } + + private static RectF getMaxCropRect(int inWidth, int inHeight, int outWidth, int outHeight, + float horizontalAlignment, float verticalAlignment) { + RectF cropRect = new RectF(); + // Get a crop rect that will fit this + if (inWidth / (float) inHeight > outWidth / (float) outHeight) { + cropRect.top = 0; + cropRect.bottom = inHeight; + float cropWidth = outWidth * (inHeight / (float) outHeight); + cropRect.left = (inWidth - cropWidth) * horizontalAlignment; + cropRect.right = cropRect.left + cropWidth; + } else { + cropRect.left = 0; + cropRect.right = inWidth; + float cropHeight = outHeight * (inWidth / (float) outWidth); + cropRect.top = (inHeight - cropHeight) * verticalAlignment; + cropRect.bottom = cropRect.top + cropHeight; + } + return cropRect; + } + + /** * Retrieve the current system wallpaper; if there is no wallpaper set, * a null pointer is returned. This is returned as an * abstract Drawable that you can install in a View to display whatever @@ -519,7 +694,7 @@ public class WallpaperManager { * * @param resid The bitmap to save. * - * @throws IOException If an error occurs reverting to the default + * @throws IOException If an error occurs reverting to the built-in * wallpaper. */ public void setResource(int resid) throws IOException { @@ -558,7 +733,7 @@ public class WallpaperManager { * * @param bitmap The bitmap to save. * - * @throws IOException If an error occurs reverting to the default + * @throws IOException If an error occurs reverting to the built-in * wallpaper. */ public void setBitmap(Bitmap bitmap) throws IOException { @@ -597,7 +772,7 @@ public class WallpaperManager { * * @param data A stream containing the raw data to install as a wallpaper. * - * @throws IOException If an error occurs reverting to the default + * @throws IOException If an error occurs reverting to the built-in * wallpaper. */ public void setStream(InputStream data) throws IOException { @@ -819,14 +994,14 @@ public class WallpaperManager { } /** - * Remove any currently set wallpaper, reverting to the system's default + * Remove any currently set wallpaper, reverting to the system's built-in * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} * is broadcast. * * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#SET_WALLPAPER}. * - * @throws IOException If an error occurs reverting to the default + * @throws IOException If an error occurs reverting to the built-in * wallpaper. */ public void clear() throws IOException { diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index e7e4a0f47fd2..6f929f261ae6 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -513,7 +513,7 @@ public final class BluetoothA2dp implements BluetoothProfile { } } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothA2dp.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 5eb642cafb09..5822e468b36b 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -322,7 +322,8 @@ public final class BluetoothDevice implements Parcelable { /** * Broadcast Action: This intent is used to broadcast PAIRING REQUEST - * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. + * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} to + * receive. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PAIRING_REQUEST = diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 196251451128..8ee955d2379d 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -885,7 +885,7 @@ public final class BluetoothHeadset implements BluetoothProfile { return false; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothHeadset.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java index b1a084a7b300..2e950faeb4e1 100644 --- a/core/java/android/bluetooth/BluetoothHealth.java +++ b/core/java/android/bluetooth/BluetoothHealth.java @@ -519,7 +519,7 @@ public final class BluetoothHealth implements BluetoothProfile { mServiceListener = null; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothHealth.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java index f9c789c58a4c..844f432ca32f 100644 --- a/core/java/android/bluetooth/BluetoothInputDevice.java +++ b/core/java/android/bluetooth/BluetoothInputDevice.java @@ -458,7 +458,7 @@ public final class BluetoothInputDevice implements BluetoothProfile { return BluetoothProfile.PRIORITY_OFF; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothInputDevice.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index fac8fd51848d..92a2f1e4253c 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -142,7 +142,6 @@ public final class BluetoothMap implements BluetoothProfile { try { mService = null; mContext.unbindService(mConnection); - mConnection = null; } catch (Exception re) { Log.e(TAG,"",re); } @@ -370,7 +369,7 @@ public final class BluetoothMap implements BluetoothProfile { return PRIORITY_OFF; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("Proxy object connected"); mService = IBluetoothMap.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index 83d4329e971d..b7a37f42b3ff 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -155,23 +155,34 @@ public final class BluetoothPan implements BluetoothProfile { /*package*/ void close() { if (VDBG) log("close()"); - if (mConnection != null) { - mContext.unbindService(mConnection); - mConnection = null; + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mStateChangeCallback); + } catch (RemoteException re) { + Log.w(TAG,"Unable to unregister BluetoothStateChangeCallback",re); + } } - mServiceListener = null; - try { - mAdapter.getBluetoothManager().unregisterStateChangeCallback(mStateChangeCallback); - } catch (RemoteException re) { - Log.w(TAG,"Unable to register BluetoothStateChangeCallback",re); + + synchronized (mConnection) { + if (mPanService != null) { + try { + mPanService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } } + mServiceListener = null; } protected void finalize() { close(); } - private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { + final private IBluetoothStateChangeCallback mStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @Override public void onBluetoothStateChange(boolean on) throws RemoteException { @@ -339,7 +350,7 @@ public final class BluetoothPan implements BluetoothProfile { return false; } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); mPanService = IBluetoothPan.Stub.asInterface(service); diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index c42251f4367b..7f456528a9fb 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -197,7 +197,6 @@ public class BluetoothPbap { try { mService = null; mContext.unbindService(mConnection); - mConnection = null; } catch (Exception re) { Log.e(TAG,"",re); } @@ -300,7 +299,7 @@ public class BluetoothPbap { } } - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) log("Proxy object connected"); mService = IBluetoothPbap.Stub.asInterface(service); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 916a6cd762b0..49dfdb5ef29d 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -1659,8 +1659,9 @@ public abstract class ContentResolver { } /** - * Return list of all Uri permission grants that have been persisted for the - * calling app. Only persistable grants taken with + * Return list of all Uri permission grants that have been persisted by the + * calling app. That is, the returned permissions have been granted + * <em>to</em> the calling app. Only persistable grants taken with * {@link #takePersistableUriPermission(Uri, int)} are returned. * * @see #takePersistableUriPermission(Uri, int) @@ -1668,7 +1669,23 @@ public abstract class ContentResolver { */ public List<UriPermission> getPersistedUriPermissions() { try { - return ActivityManagerNative.getDefault().getPersistedUriPermissions().getList(); + return ActivityManagerNative.getDefault() + .getPersistedUriPermissions(mPackageName, true).getList(); + } catch (RemoteException e) { + throw new RuntimeException("Activity manager has died", e); + } + } + + /** + * Return list of all persisted Uri permission grants that are hosted by the + * calling app. That is, the returned permissions have been granted + * <em>from</em> the calling app. Only grants taken with + * {@link #takePersistableUriPermission(Uri, int)} are returned. + */ + public List<UriPermission> getOutgoingPersistedUriPermissions() { + try { + return ActivityManagerNative.getDefault() + .getPersistedUriPermissions(mPackageName, false).getList(); } catch (RemoteException e) { throw new RuntimeException("Activity manager has died", e); } diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 5760a5d30b9e..dad0dfb91a75 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -722,6 +722,14 @@ public class IntentFilter implements Parcelable { * included in the filter, then an Intent's data must match one of * them. If no scheme specific parts are included, then only the scheme must match. * + * <p>The "scheme specific part" that this matches against is the string returned + * by {@link android.net.Uri#getSchemeSpecificPart() Uri.getSchemeSpecificPart}. + * For Uris that contain a path, this kind of matching is not generally of interest, + * since {@link #addDataAuthority(String, String)} and + * {@link #addDataPath(String, int)} can provide a better mechanism for matching + * them. However, for Uris that do not contain a path, the authority and path + * are empty, so this is the only way to match against the non-scheme part.</p> + * * @param ssp Either a raw string that must exactly match the scheme specific part * path, or a simple pattern, depending on <var>type</var>. * @param type Determines how <var>ssp</var> will be compared to diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index acd4ffa1a7fc..267fb2af2dd1 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -123,6 +123,9 @@ interface IPackageManager { List<ResolveInfo> queryIntentServices(in Intent intent, String resolvedType, int flags, int userId); + List<ResolveInfo> queryIntentContentProviders(in Intent intent, + String resolvedType, int flags, int userId); + /** * This implements getInstalledPackages via a "last returned row" * mechanism that is not exposed in the API. This is to get around the IPC diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b63db8a8856c..8b8c58b87076 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2210,6 +2210,24 @@ public abstract class PackageManager { public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId); + /** {@hide} */ + public abstract List<ResolveInfo> queryIntentContentProvidersAsUser( + Intent intent, int flags, int userId); + + /** + * Retrieve all providers that can match the given intent. + * + * @param intent An intent containing all of the desired specification + * (action, data, type, category, and/or component). + * @param flags Additional option flags. + * @return A List<ResolveInfo> containing one entry for each matching + * ProviderInfo. These are ordered from best to worst match. If + * there are no matching providers, an empty list is returned. + * @see #GET_INTENT_FILTERS + * @see #GET_RESOLVED_FILTER + */ + public abstract List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags); + /** * Find a single content provider by its base path name. * diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index b489ee9e2988..17d13e500e8e 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2819,7 +2819,14 @@ public class PackageParser { continue; } - if (parser.getName().equals("meta-data")) { + if (parser.getName().equals("intent-filter")) { + ProviderIntentInfo intent = new ProviderIntentInfo(outInfo); + if (!parseIntent(res, parser, attrs, true, intent, outError)) { + return false; + } + outInfo.intents.add(intent); + + } else if (parser.getName().equals("meta-data")) { if ((outInfo.metaData=parseMetaData(res, parser, attrs, outInfo.metaData, outError)) == null) { return false; @@ -3982,7 +3989,7 @@ public class PackageParser { return si; } - public final static class Provider extends Component { + public final static class Provider extends Component<ProviderIntentInfo> { public final ProviderInfo info; public boolean syncable; @@ -4116,6 +4123,24 @@ public class PackageParser { } } + public static final class ProviderIntentInfo extends IntentInfo { + public final Provider provider; + + public ProviderIntentInfo(Provider provider) { + this.provider = provider; + } + + public String toString() { + StringBuilder sb = new StringBuilder(128); + sb.append("ProviderIntentInfo{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + sb.append(' '); + provider.appendComponentShortName(sb); + sb.append('}'); + return sb.toString(); + } + } + /** * @hide */ diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index a53417620cc0..f6ea058b526f 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -19,6 +19,7 @@ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; import android.os.PatternMatcher; +import android.util.Printer; /** * Holds information about a specific @@ -112,7 +113,13 @@ public final class ProviderInfo extends ComponentInfo flags = orig.flags; isSyncable = orig.isSyncable; } - + + public void dump(Printer pw, String prefix) { + super.dumpFront(pw, prefix); + pw.println(prefix + "authority=" + authority); + pw.println(prefix + "flags=0x" + Integer.toHexString(flags)); + } + public int describeContents() { return 0; } diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index e360e4063f7a..1ff41c022186 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -23,6 +23,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Printer; +import android.util.Slog; import java.text.Collator; import java.util.Comparator; @@ -34,20 +35,30 @@ import java.util.Comparator; * <intent> tags. */ public class ResolveInfo implements Parcelable { + private static final String TAG = "ResolveInfo"; + /** - * The activity or broadcast receiver that corresponds to this resolution match, - * if this resolution is for an activity or broadcast receiver. One and only one of this and - * serviceInfo must be non-null. + * The activity or broadcast receiver that corresponds to this resolution + * match, if this resolution is for an activity or broadcast receiver. + * Exactly one of {@link #activityInfo}, {@link #serviceInfo}, or + * {@link #providerInfo} will be non-null. */ public ActivityInfo activityInfo; /** - * The service that corresponds to this resolution match, if this - * resolution is for a service. One and only one of this and - * activityInfo must be non-null. + * The service that corresponds to this resolution match, if this resolution + * is for a service. Exactly one of {@link #activityInfo}, + * {@link #serviceInfo}, or {@link #providerInfo} will be non-null. */ public ServiceInfo serviceInfo; - + + /** + * The provider that corresponds to this resolution match, if this + * resolution is for a provider. Exactly one of {@link #activityInfo}, + * {@link #serviceInfo}, or {@link #providerInfo} will be non-null. + */ + public ProviderInfo providerInfo; + /** * The IntentFilter that was matched for this ResolveInfo. */ @@ -120,6 +131,13 @@ public class ResolveInfo implements Parcelable { */ public boolean system; + private ComponentInfo getComponentInfo() { + if (activityInfo != null) return activityInfo; + if (serviceInfo != null) return serviceInfo; + if (providerInfo != null) return providerInfo; + throw new IllegalStateException("Missing ComponentInfo!"); + } + /** * Retrieve the current textual label associated with this resolution. This * will call back on the given PackageManager to load the label from @@ -142,7 +160,7 @@ public class ResolveInfo implements Parcelable { return label.toString().trim(); } } - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + ComponentInfo ci = getComponentInfo(); ApplicationInfo ai = ci.applicationInfo; if (labelRes != 0) { label = pm.getText(ci.packageName, labelRes, ai); @@ -176,7 +194,7 @@ public class ResolveInfo implements Parcelable { return dr; } } - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + ComponentInfo ci = getComponentInfo(); ApplicationInfo ai = ci.applicationInfo; if (icon != 0) { dr = pm.getDrawable(ci.packageName, icon, ai); @@ -196,8 +214,8 @@ public class ResolveInfo implements Parcelable { */ public final int getIconResource() { if (icon != 0) return icon; - if (activityInfo != null) return activityInfo.getIconResource(); - if (serviceInfo != null) return serviceInfo.getIconResource(); + final ComponentInfo ci = getComponentInfo(); + if (ci != null) return ci.getIconResource(); return 0; } @@ -225,6 +243,9 @@ public class ResolveInfo implements Parcelable { } else if (serviceInfo != null) { pw.println(prefix + "ServiceInfo:"); serviceInfo.dump(pw, prefix + " "); + } else if (providerInfo != null) { + pw.println(prefix + "ProviderInfo:"); + providerInfo.dump(pw, prefix + " "); } } @@ -234,6 +255,7 @@ public class ResolveInfo implements Parcelable { public ResolveInfo(ResolveInfo orig) { activityInfo = orig.activityInfo; serviceInfo = orig.serviceInfo; + providerInfo = orig.providerInfo; filter = orig.filter; priority = orig.priority; preferredOrder = orig.preferredOrder; @@ -247,7 +269,7 @@ public class ResolveInfo implements Parcelable { } public String toString() { - ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; + final ComponentInfo ci = getComponentInfo(); StringBuilder sb = new StringBuilder(128); sb.append("ResolveInfo{"); sb.append(Integer.toHexString(System.identityHashCode(this))); @@ -278,6 +300,9 @@ public class ResolveInfo implements Parcelable { } else if (serviceInfo != null) { dest.writeInt(2); serviceInfo.writeToParcel(dest, parcelableFlags); + } else if (providerInfo != null) { + dest.writeInt(3); + providerInfo.writeToParcel(dest, parcelableFlags); } else { dest.writeInt(0); } @@ -309,18 +334,21 @@ public class ResolveInfo implements Parcelable { }; private ResolveInfo(Parcel source) { + activityInfo = null; + serviceInfo = null; + providerInfo = null; switch (source.readInt()) { case 1: activityInfo = ActivityInfo.CREATOR.createFromParcel(source); - serviceInfo = null; break; case 2: serviceInfo = ServiceInfo.CREATOR.createFromParcel(source); - activityInfo = null; + break; + case 3: + providerInfo = ProviderInfo.CREATOR.createFromParcel(source); break; default: - activityInfo = null; - serviceInfo = null; + Slog.w(TAG, "Missing ComponentInfo!"); break; } if (source.readInt() != 0) { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 85fa7d6885e0..4fe2c4d3669b 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -487,6 +487,12 @@ public final class CameraCharacteristics extends CameraMetadata { * Gain factor from electrons to raw units when * ISO=100 * </p> + * + * <b>Optional</b> - This value may be null on some devices. + * + * <b>{@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL}</b> - + * Present on all devices that report being FULL level hardware devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL HARDWARE_LEVEL} key. */ public static final Key<Rational> SENSOR_BASE_GAIN_FACTOR = new Key<Rational>("android.sensor.baseGainFactor", Rational.class); @@ -502,6 +508,12 @@ public final class CameraCharacteristics extends CameraMetadata { * values above this, it can be a mix of analog and * digital * </p> + * + * <b>Optional</b> - This value may be null on some devices. + * + * <b>{@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL}</b> - + * Present on all devices that report being FULL level hardware devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL HARDWARE_LEVEL} key. */ public static final Key<Integer> SENSOR_MAX_ANALOG_SENSITIVITY = new Key<Integer>("android.sensor.maxAnalogSensitivity", int.class); diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index a9a72b074df8..7095e4d498ab 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -197,26 +197,33 @@ public interface CameraDevice extends AutoCloseable { * if the format is user-visible, it must be one of android.scaler.availableFormats; * and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p> * - * <p>To change the output, the camera device must be idle. The device is considered - * to be idle once all in-flight and pending capture requests have been processed, - * and all output image buffers from the captures have been sent to their destination - * Surfaces.</p> - * - * <p>To reach an idle state without cancelling any submitted captures, first - * stop any repeating request/burst with {@link #stopRepeating}, and then - * wait for the {@link StateListener#onIdle} callback to be - * called. To idle as fast as possible, use {@link #flush} and wait for the - * idle callback.</p> + * <p>When this method is called with valid Surfaces, the device will transition to the {@link + * StateListener#onBusy busy state}. Once configuration is complete, the device will transition + * into the {@link StateListener#onIdle idle state}. Capture requests using the newly-configured + * Surfaces may then be submitted with {@link #capture}, {@link #captureBurst}, {@link + * #setRepeatingRequest}, or {@link #setRepeatingBurst}.</p> + * + * <p>If this method is called while the camera device is still actively processing previously + * submitted captures, then the following sequence of events occurs: The device transitions to + * the busy state and calls the {@link StateListener#onBusy} callback. Second, if a repeating + * request is set it is cleared. Third, the device finishes up all in-flight and pending + * requests. Finally, once the device is idle, it then reconfigures its outputs, and calls the + * {@link StateListener#onIdle} method once it is again ready to accept capture + * requests. Therefore, no submitted work is discarded. To idle as fast as possible, use {@link + * #flush} and wait for the idle callback before calling configureOutputs. This will discard + * work, but reaches the new configuration sooner.</p> * * <p>Using larger resolution outputs, or more outputs, can result in slower * output rate from the device.</p> * - * <p>Configuring the outputs with an empty or null list will transition - * the camera into an {@link StateListener#onUnconfigured unconfigured state}. - * </p> + * <p>Configuring the outputs with an empty or null list will transition the camera into an + * {@link StateListener#onUnconfigured unconfigured state} instead of the {@link + * StateListener#onIdle idle state}. </p> * * <p>Calling configureOutputs with the same arguments as the last call to - * configureOutputs has no effect.</p> + * configureOutputs has no effect, and the {@link StateListener#onBusy busy} + * and {@link StateListener#onIdle idle} state transitions will happen + * immediately.</p> * * @param outputs The new set of Surfaces that should be made available as * targets for captured image data. @@ -228,7 +235,10 @@ public interface CameraDevice extends AutoCloseable { * @throws IllegalStateException if the camera device is not idle, or * if the camera device has been closed * + * @see StateListener#onBusy * @see StateListener#onIdle + * @see StateListener#onActive + * @see StateListener#onUnconfigured * @see #stopRepeating * @see #flush */ @@ -516,31 +526,6 @@ public interface CameraDevice extends AutoCloseable { public void waitUntilIdle() throws CameraAccessException; /** - * Set the listener object to call when an asynchronous device event occurs, - * such as errors or idle notifications. - * - * <p>The events reported here are device-wide; notifications about - * individual capture requests or capture results are reported through - * {@link CaptureListener}.</p> - * - * <p>If the camera device is idle when the listener is set, then the - * {@link StateListener#onIdle} method will be immediately called, - * even if the device has never been active before. - * </p> - * - * @param listener the CameraDeviceListener to send device-level event - * notifications to. Setting this to null will stop notifications. - * @param handler the handler on which the listener should be invoked, or - * {@code null} to use the current thread's {@link android.os.Looper looper}. - * - * @throws IllegalArgumentException if handler is null, the listener is - * not null, and the calling thread has no looper - * - * @hide - */ - public void setDeviceListener(StateListener listener, Handler handler); - - /** * Flush all captures currently pending and in-progress as fast as * possible. * @@ -577,13 +562,24 @@ public interface CameraDevice extends AutoCloseable { public void flush() throws CameraAccessException; /** - * Close the connection to this camera device. After this call, all calls to + * Close the connection to this camera device. + * + * <p>After this call, all calls to * the camera device interface will throw a {@link IllegalStateException}, - * except for calls to close(). + * except for calls to close(). Once the device has fully shut down, the + * {@link StateListener#onClosed} callback will be called, and the camera is + * free to be re-opened.</p> + * + * <p>After this call, besides the final {@link StateListener#onClosed} call, no calls to the + * device's {@link StateListener} will occur, and any remaining submitted capture requests will + * not fire their {@link CaptureListener} callbacks.</p> + * + * <p>To shut down as fast as possible, call the {@link #flush} method and then {@link #close} + * once the flush completes. This will discard some capture requests, but results in faster + * shutdown.</p> */ @Override public void close(); - // TODO: We should decide on the behavior of in-flight requests should be on close. /** * <p>A listener for tracking the progress of a {@link CaptureRequest} @@ -713,6 +709,9 @@ public interface CameraDevice extends AutoCloseable { * A listener for notifications 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>These events include notifications about the device becoming idle ( * allowing for {@link #configureOutputs} to be called), about device * disconnection, and about unexpected device errors.</p> @@ -722,7 +721,7 @@ public interface CameraDevice extends AutoCloseable { * the {@link #capture}, {@link #captureBurst}, {@link * #setRepeatingRequest}, or {@link #setRepeatingBurst} methods. * - * @see #setDeviceListener + * @see CameraManager#openCamera */ public static abstract class StateListener { /** diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index f5ee367c70ca..65b6c7a09443 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -197,6 +197,8 @@ public final class CameraManager { * {@link #openCamera}. * * @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. * * @throws CameraAccessException if the camera is disabled by device policy, * or too many camera devices are already open, or the cameraId does not match @@ -204,11 +206,14 @@ public final class CameraManager { * * @throws SecurityException if the application does not have permission to * access the camera + * @throws IllegalArgumentException if listener or handler is null. * * @see #getCameraIdList * @see android.app.admin.DevicePolicyManager#setCameraDisabled */ - private CameraDevice openCamera(String cameraId) throws CameraAccessException { + private void openCameraDeviceUserAsync(String cameraId, + CameraDevice.StateListener listener, Handler handler) + throws CameraAccessException { try { synchronized (mLock) { @@ -216,7 +221,10 @@ public final class CameraManager { ICameraDeviceUser cameraUser; android.hardware.camera2.impl.CameraDevice device = - new android.hardware.camera2.impl.CameraDevice(cameraId); + new android.hardware.camera2.impl.CameraDevice( + cameraId, + listener, + handler); BinderHolder holder = new BinderHolder(); mCameraService.connectDevice(device.getCallbacks(), @@ -225,10 +233,9 @@ public final class CameraManager { cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder()); // TODO: factor out listener to be non-nested, then move setter to constructor + // For now, calling setRemoteDevice will fire initial + // onOpened/onUnconfigured callbacks. device.setRemoteDevice(cameraUser); - - return device; - } } catch (NumberFormatException e) { @@ -238,7 +245,6 @@ public final class CameraManager { throw e.asChecked(); } catch (RemoteException e) { // impossible - return null; } } @@ -303,16 +309,7 @@ public final class CameraManager { } } - final CameraDevice camera = openCamera(cameraId); - camera.setDeviceListener(listener, handler); - - // TODO: make truly async in the camera service - handler.post(new Runnable() { - @Override - public void run() { - listener.onOpened(camera); - } - }); + openCameraDeviceUserAsync(cameraId, listener, handler); } /** diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index f30bcc541ecf..898f1232b832 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -82,6 +82,7 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable { private CaptureRequest(CaptureRequest source) { mSettings = new CameraMetadataNative(source.mSettings); mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone(); + mUserTag = source.mUserTag; } /** diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index c9626f1b074e..dbd0457e525f 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -60,11 +60,6 @@ public final class CaptureResult extends CameraMetadata { @Override public <T> T get(Key<T> key) { - if (key == STATISTICS_FACES) { // Don't throw IllegalArgumentException - // TODO: Implement android.statistics.faces - return null; - } - return mResults.get(key); } @@ -727,6 +722,12 @@ public final class CaptureResult extends CameraMetadata { * The thermal diode being queried should be inside the sensor PCB, or * somewhere close to it. * </p> + * + * <b>Optional</b> - This value may be null on some devices. + * + * <b>{@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL}</b> - + * Present on all devices that report being FULL level hardware devices in the + * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL HARDWARE_LEVEL} key. */ public static final Key<Float> SENSOR_TEMPERATURE = new Key<Float>("android.sensor.temperature", float.class); diff --git a/core/java/android/hardware/camera2/Face.java b/core/java/android/hardware/camera2/Face.java index ef068ca7ec61..ded8839dc15c 100644 --- a/core/java/android/hardware/camera2/Face.java +++ b/core/java/android/hardware/camera2/Face.java @@ -58,6 +58,9 @@ public final class Face { * Create a new face with all fields set. * * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. + * They are only required when the {@link CaptureResult} reports that the value of key + * {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} is + * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_FULL}. * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, * rightEyePosition, and mouthPosition may be independently null or not-null.</p> @@ -107,7 +110,11 @@ public final class Face { * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, - * rightEyePosition, and mouthPosition may be independently null or not-null.</p> + * rightEyePosition, and mouthPosition may be independently null or not-null. When devices + * report the value of key {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} as + * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_SIMPLE} in {@link CaptureResult}, + * the face id of each face is expected to be {@value #ID_UNSUPPORTED}, the leftEyePosition, + * rightEyePosition, and mouthPositions are expected to be {@code null} for each face.</p> * * @param bounds Bounds of the face. * @param score Confidence level between {@value #SCORE_MIN}-{@value #SCORE_MAX}. @@ -168,7 +175,10 @@ public final class Face { * <p>This is an optional field, may not be supported on all devices. * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, - * rightEyePosition, and mouthPosition may be independently null or not-null.</p> + * rightEyePosition, and mouthPosition may be independently null or not-null. When devices + * report the value of key {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} as + * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_SIMPLE} in {@link CaptureResult}, + * the face id of each face is expected to be {@value #ID_UNSUPPORTED}.</p> * * <p>This value will either be {@value #ID_UNSUPPORTED} or * otherwise greater than {@code 0}.</p> @@ -219,7 +229,7 @@ public final class Face { * field, may not be supported on all devices. If not * supported, the value will always be set to null. * This value will always be null only if {@link #getId()} returns - * {@value #ID_UNSUPPORTED}.</p> them are. + * {@value #ID_UNSUPPORTED}.</p> * </p> * * @return The mouth position, or {@code null} if unknown. diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java index 463063c1fb2a..c5d099921306 100644 --- a/core/java/android/hardware/camera2/impl/CameraDevice.java +++ b/core/java/android/hardware/camera2/impl/CameraDevice.java @@ -55,8 +55,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { private final Object mLock = new Object(); private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks(); - private StateListener mDeviceListener; - private Handler mDeviceHandler; + private final StateListener mDeviceListener; + private final Handler mDeviceHandler; + + private boolean mIdle = true; private final SparseArray<CaptureListenerHolder> mCaptureListenerMap = new SparseArray<CaptureListenerHolder>(); @@ -67,8 +69,72 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { private final String mCameraId; - public CameraDevice(String cameraId) { + // Runnables for all state transitions, except error, which needs the + // error code argument + + private final Runnable mCallOnOpened = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onOpened(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnUnconfigured = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onUnconfigured(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnActive = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onActive(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnBusy = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onBusy(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnClosed = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onClosed(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnIdle = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onIdle(CameraDevice.this); + } + } + }; + + private final Runnable mCallOnDisconnected = new Runnable() { + public void run() { + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onDisconnected(CameraDevice.this); + } + } + }; + + public CameraDevice(String cameraId, StateListener listener, Handler handler) { + if (cameraId == null || listener == null || handler == null) { + throw new IllegalArgumentException("Null argument given"); + } mCameraId = cameraId; + mDeviceListener = listener; + mDeviceHandler = handler; TAG = String.format("CameraDevice-%s-JV", mCameraId); DEBUG = Log.isLoggable(TAG, Log.DEBUG); } @@ -79,7 +145,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { public void setRemoteDevice(ICameraDeviceUser remoteDevice) { // TODO: Move from decorator to direct binder-mediated exceptions - mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice); + synchronized(mLock) { + mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice); + + mDeviceHandler.post(mCallOnOpened); + mDeviceHandler.post(mCallOnUnconfigured); + } } @Override @@ -89,7 +160,13 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { @Override public void configureOutputs(List<Surface> outputs) throws CameraAccessException { + // Treat a null input the same an empty list + if (outputs == null) { + outputs = new ArrayList<Surface>(); + } synchronized (mLock) { + checkIfCameraClosed(); + HashSet<Surface> addSet = new HashSet<Surface>(outputs); // Streams to create List<Integer> deleteList = new ArrayList<Integer>(); // Streams to delete @@ -105,9 +182,13 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } } + mDeviceHandler.post(mCallOnBusy); + stopRepeating(); + try { - // TODO: mRemoteDevice.beginConfigure + mRemoteDevice.waitUntilIdle(); + // TODO: mRemoteDevice.beginConfigure // Delete all streams first (to free up HW resources) for (Integer streamId : deleteList) { mRemoteDevice.deleteStream(streamId); @@ -126,7 +207,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } catch (CameraRuntimeException e) { if (e.getReason() == CAMERA_IN_USE) { throw new IllegalStateException("The camera is currently busy." + - " You must call waitUntilIdle before trying to reconfigure."); + " You must wait until the previous operation completes."); } throw e.asChecked(); @@ -134,6 +215,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { // impossible return; } + + if (outputs.size() > 0) { + mDeviceHandler.post(mCallOnIdle); + } else { + mDeviceHandler.post(mCallOnUnconfigured); + } } } @@ -141,6 +228,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { public CaptureRequest.Builder createCaptureRequest(int templateType) throws CameraAccessException { synchronized (mLock) { + checkIfCameraClosed(); CameraMetadataNative templatedRequest = new CameraMetadataNative(); @@ -188,7 +276,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } synchronized (mLock) { - + checkIfCameraClosed(); int requestId; try { @@ -208,6 +296,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { mRepeatingRequestIdStack.add(requestId); } + if (mIdle) { + mDeviceHandler.post(mCallOnActive); + } + mIdle = false; + return requestId; } } @@ -233,7 +326,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { public void stopRepeating() throws CameraAccessException { synchronized (mLock) { - + checkIfCameraClosed(); while (!mRepeatingRequestIdStack.isEmpty()) { int requestId = mRepeatingRequestIdStack.pop(); @@ -270,20 +363,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } @Override - public void setDeviceListener(StateListener listener, Handler handler) { - synchronized (mLock) { - if (listener != null) { - handler = checkHandler(handler); - } - - mDeviceListener = listener; - mDeviceHandler = handler; - } - } - - @Override public void flush() throws CameraAccessException { synchronized (mLock) { + checkIfCameraClosed(); + + mDeviceHandler.post(mCallOnBusy); try { mRemoteDevice.flush(); } catch (CameraRuntimeException e) { @@ -297,9 +381,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { @Override public void close() { - - // TODO: every method should throw IllegalStateException after close has been called - synchronized (mLock) { try { @@ -312,8 +393,11 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { // impossible } - mRemoteDevice = null; + if (mRemoteDevice != null) { + mDeviceHandler.post(mCallOnClosed); + } + mRemoteDevice = null; } } @@ -399,49 +483,44 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { @Override public void onCameraError(final int errorCode) { - synchronized (mLock) { - if (CameraDevice.this.mDeviceListener == null) return; - final StateListener listener = CameraDevice.this.mDeviceListener; - Runnable r = null; + Runnable r = null; + if (isClosed()) return; + + synchronized(mLock) { switch (errorCode) { case ERROR_CAMERA_DISCONNECTED: - r = new Runnable() { - public void run() { - listener.onDisconnected(CameraDevice.this); - } - }; + r = mCallOnDisconnected; break; + default: + Log.e(TAG, "Unknown error from camera device: " + errorCode); + // no break case ERROR_CAMERA_DEVICE: case ERROR_CAMERA_SERVICE: r = new Runnable() { public void run() { - listener.onError(CameraDevice.this, errorCode); + if (!CameraDevice.this.isClosed()) { + mDeviceListener.onError(CameraDevice.this, errorCode); + } } }; break; - default: - Log.e(TAG, "Unknown error from camera device: " + errorCode); - } - if (r != null) { - CameraDevice.this.mDeviceHandler.post(r); } + CameraDevice.this.mDeviceHandler.post(r); } } @Override public void onCameraIdle() { + if (isClosed()) return; + if (DEBUG) { Log.d(TAG, "Camera now idle"); } synchronized (mLock) { - if (CameraDevice.this.mDeviceListener == null) return; - final StateListener listener = CameraDevice.this.mDeviceListener; - Runnable r = new Runnable() { - public void run() { - listener.onIdle(CameraDevice.this); - } - }; - CameraDevice.this.mDeviceHandler.post(r); + if (!CameraDevice.this.mIdle) { + CameraDevice.this.mDeviceHandler.post(mCallOnIdle); + } + CameraDevice.this.mIdle = true; } } @@ -461,14 +540,18 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { return; } + if (isClosed()) return; + // Dispatch capture start notice holder.getHandler().post( new Runnable() { public void run() { - holder.getListener().onCaptureStarted( - CameraDevice.this, - holder.getRequest(), - timestamp); + if (!CameraDevice.this.isClosed()) { + holder.getListener().onCaptureStarted( + CameraDevice.this, + holder.getRequest(), + timestamp); + } } }); } @@ -503,6 +586,8 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { return; } + if (isClosed()) return; + final CaptureRequest request = holder.getRequest(); final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId); @@ -510,10 +595,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { new Runnable() { @Override public void run() { - holder.getListener().onCaptureCompleted( - CameraDevice.this, - request, - resultAsCapture); + if (!CameraDevice.this.isClosed()){ + holder.getListener().onCaptureCompleted( + CameraDevice.this, + request, + resultAsCapture); + } } }); } @@ -541,4 +628,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { throw new IllegalStateException("CameraDevice was already closed"); } } + + private boolean isClosed() { + synchronized(mLock) { + return (mRemoteDevice == null); + } + } } diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 89ffd936b40a..adccbc57c5c7 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -16,7 +16,13 @@ package android.hardware.camera2.impl; +import android.graphics.ImageFormat; +import android.graphics.Point; +import android.graphics.Rect; +import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraMetadata; +import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.Face; import android.hardware.camera2.Rational; import android.os.Parcelable; import android.os.Parcel; @@ -36,6 +42,8 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable { private static final String TAG = "CameraMetadataJV"; private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); + // this should be in sync with HAL_PIXEL_FORMAT_BLOB defined in graphics.h + private static final int NATIVE_JPEG_FORMAT = 0x21; public CameraMetadataNative() { super(); @@ -84,16 +92,21 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable { @SuppressWarnings("unchecked") @Override public <T> T get(Key<T> key) { - int tag = key.getTag(); - byte[] values = readValues(tag); - if (values == null) { + + if (key == CaptureResult.STATISTICS_FACES) { + /** + * FIXME: Workaround for HAL bug that's missing FACE_DETECT_MODE + */ + Log.w(TAG, "Expected non-null android.statistics.faceDetectMode"); return null; } - int nativeType = getNativeType(tag); + T value = getOverride(key); + if (value != null) { + return value; + } - ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); - return unpackSingle(buffer, key.getType(), nativeType); + return getBase(key); } public void readFromParcel(Parcel in) { @@ -110,24 +123,11 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable { * type to the key. */ public <T> void set(Key<T> key, T value) { - int tag = key.getTag(); - - if (value == null) { - writeValues(tag, null); + if (setOverride(key, value)) { return; } - int nativeType = getNativeType(tag); - - int size = packSingle(value, null, key.getType(), nativeType, /* sizeOnly */true); - - // TODO: Optimization. Cache the byte[] and reuse if the size is big enough. - byte[] values = new byte[size]; - - ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); - packSingle(value, buffer, key.getType(), nativeType, /*sizeOnly*/false); - - writeValues(tag, values); + setBase(key, value); } // Keep up-to-date with camera_metadata.h @@ -435,6 +435,157 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable { return (T) array; } + private <T> T getBase(Key<T> key) { + int tag = key.getTag(); + byte[] values = readValues(tag); + if (values == null) { + return null; + } + + int nativeType = getNativeType(tag); + + ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); + return unpackSingle(buffer, key.getType(), nativeType); + } + + // Need overwrite some metadata that has different definitions between native + // and managed sides. + @SuppressWarnings("unchecked") + private <T> T getOverride(Key<T> key) { + if (key == CameraCharacteristics.SCALER_AVAILABLE_FORMATS) { + return (T) getAvailableFormats(); + } else if (key == CaptureResult.STATISTICS_FACES) { + return (T) getFaces(); + } + + // For other keys, get() falls back to getBase() + return null; + } + + private int[] getAvailableFormats() { + int[] availableFormats = getBase(CameraCharacteristics.SCALER_AVAILABLE_FORMATS); + for (int i = 0; i < availableFormats.length; i++) { + // JPEG has different value between native and managed side, need override. + if (availableFormats[i] == NATIVE_JPEG_FORMAT) { + availableFormats[i] = ImageFormat.JPEG; + } + } + return availableFormats; + } + + private Face[] getFaces() { + final int FACE_LANDMARK_SIZE = 6; + + Integer faceDetectMode = getBase(CaptureResult.STATISTICS_FACE_DETECT_MODE); + if (faceDetectMode == null) { + throw new AssertionError("Expect non-null face detect mode"); + } + + if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_OFF) { + return new Face[0]; + } + if (faceDetectMode != CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE && + faceDetectMode != CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) { + throw new AssertionError("Unknown face detect mode: " + faceDetectMode); + } + + // Face scores and rectangles are required by SIMPLE and FULL mode. + byte[] faceScores = getBase(CaptureResult.STATISTICS_FACE_SCORES); + Rect[] faceRectangles = getBase(CaptureResult.STATISTICS_FACE_RECTANGLES); + if (faceScores == null || faceRectangles == null) { + throw new AssertionError("Expect face scores and rectangles to be non-null"); + } else if (faceScores.length != faceRectangles.length) { + throw new AssertionError( + String.format("Face score size(%d) doesn match face rectangle size(%d)!", + faceScores.length, faceRectangles.length)); + } + + // Face id and landmarks are only required by FULL mode. + int[] faceIds = getBase(CaptureResult.STATISTICS_FACE_IDS); + int[] faceLandmarks = getBase(CaptureResult.STATISTICS_FACE_LANDMARKS); + int numFaces = faceScores.length; + if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) { + if (faceIds == null || faceLandmarks == null) { + throw new AssertionError("Expect face ids and landmarks to be non-null for " + + "FULL mode"); + } else if (faceIds.length != numFaces || + faceLandmarks.length != numFaces * FACE_LANDMARK_SIZE) { + throw new AssertionError( + String.format("Face id size(%d), or face landmark size(%d) don't match " + + "face number(%d)!", + faceIds.length, faceLandmarks.length * FACE_LANDMARK_SIZE, + numFaces)); + } + } + + Face[] faces = new Face[numFaces]; + if (faceDetectMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE) { + for (int i = 0; i < numFaces; i++) { + faces[i] = new Face(faceRectangles[i], faceScores[i]); + } + } else { + // CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL + for (int i = 0; i < numFaces; i++) { + Point leftEye = new Point(faceLandmarks[i*6], faceLandmarks[i*6+1]); + Point rightEye = new Point(faceLandmarks[i*6+2], faceLandmarks[i*6+3]); + Point mouth = new Point(faceLandmarks[i*6+4], faceLandmarks[i*6+5]); + faces[i] = new Face(faceRectangles[i], faceScores[i], faceIds[i], + leftEye, rightEye, mouth); + } + } + return faces; + } + + private <T> void setBase(Key<T> key, T value) { + int tag = key.getTag(); + + if (value == null) { + writeValues(tag, null); + return; + } + + int nativeType = getNativeType(tag); + + int size = packSingle(value, null, key.getType(), nativeType, /* sizeOnly */true); + + // TODO: Optimization. Cache the byte[] and reuse if the size is big enough. + byte[] values = new byte[size]; + + ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); + packSingle(value, buffer, key.getType(), nativeType, /*sizeOnly*/false); + + writeValues(tag, values); + } + + // Set the camera metadata override. + private <T> boolean setOverride(Key<T> key, T value) { + if (key == CameraCharacteristics.SCALER_AVAILABLE_FORMATS) { + return setAvailableFormats((int[]) value); + } + + // For other keys, set() falls back to setBase(). + return false; + } + + private boolean setAvailableFormats(int[] value) { + int[] availableFormat = value; + if (value == null) { + // Let setBase() to handle the null value case. + return false; + } + + int[] newValues = new int[availableFormat.length]; + for (int i = 0; i < availableFormat.length; i++) { + newValues[i] = availableFormat[i]; + if (availableFormat[i] == ImageFormat.JPEG) { + newValues[i] = NATIVE_JPEG_FORMAT; + } + } + + setBase(CameraCharacteristics.SCALER_AVAILABLE_FORMATS, newValues); + return true; + } + private long mMetadataPtr; // native CameraMetadata* private native long nativeAllocate(); @@ -538,7 +689,7 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable { * @hide */ public byte[] readValues(int tag) { - // TODO: Optimization. Native code returns a ByteBuffer instead. + // TODO: Optimization. Native code returns a ByteBuffer instead. return nativeReadValues(tag); } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 9319d4a90201..1b7d9eab9fc1 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -687,6 +687,8 @@ public class InputMethodService extends AbstractInputMethodService { mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService); mRootView = mInflater.inflate( com.android.internal.R.layout.input_method, null); + mRootView.setSystemUiVisibility( + View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); mWindow.setContentView(mRootView); mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer); if (Settings.Global.getInt(getContentResolver(), diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java index 648a4b37ebb3..78ac75f22c36 100644 --- a/core/java/android/net/ProxyProperties.java +++ b/core/java/android/net/ProxyProperties.java @@ -178,7 +178,7 @@ public class ProxyProperties implements Parcelable { // If PAC URL is present in either then they must be equal. // Other parameters will only be for fall back. if (!TextUtils.isEmpty(mPacFileUrl)) { - return mPacFileUrl.equals(p.getPacFileUrl()); + return mPacFileUrl.equals(p.getPacFileUrl()) && mPort == p.mPort; } if (!TextUtils.isEmpty(p.getPacFileUrl())) { return false; @@ -219,6 +219,7 @@ public class ProxyProperties implements Parcelable { if (mPacFileUrl != null) { dest.writeByte((byte)1); dest.writeString(mPacFileUrl); + dest.writeInt(mPort); return; } else { dest.writeByte((byte)0); @@ -244,7 +245,9 @@ public class ProxyProperties implements Parcelable { String host = null; int port = 0; if (in.readByte() != 0) { - return new ProxyProperties(in.readString()); + String url = in.readString(); + int localPort = in.readInt(); + return new ProxyProperties(url, localPort); } if (in.readByte() != 0) { host = in.readString(); diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index fc53580f9cc1..db5cf1c4094e 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -24,9 +24,11 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.GuardedBy; +import com.google.android.collect.Lists; import java.io.File; import java.io.IOException; +import java.util.ArrayList; /** * Provides access to environment variables. @@ -38,6 +40,7 @@ public class Environment { private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; + private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE"; private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT"; /** {@hide} */ @@ -107,7 +110,6 @@ public class Environment { /** {@hide} */ public static class UserEnvironment { // TODO: generalize further to create package-specific environment - // TODO: add support for secondary external storage /** External storage dirs, as visible to vold */ private final File[] mExternalDirsForVold; @@ -121,11 +123,15 @@ public class Environment { String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE); String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE); String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET); + String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE); if (TextUtils.isEmpty(rawMediaStorage)) { rawMediaStorage = "/data/media"; } + ArrayList<File> externalForVold = Lists.newArrayList(); + ArrayList<File> externalForApp = Lists.newArrayList(); + if (!TextUtils.isEmpty(rawEmulatedTarget)) { // Device has emulated storage; external storage paths should have // userId burned into them. @@ -135,8 +141,8 @@ public class Environment { final File mediaBase = new File(rawMediaStorage); // /storage/emulated/0 - mExternalDirsForVold = new File[] { buildPath(emulatedSourceBase, rawUserId) }; - mExternalDirsForApp = new File[] { buildPath(emulatedTargetBase, rawUserId) }; + externalForVold.add(buildPath(emulatedSourceBase, rawUserId)); + externalForApp.add(buildPath(emulatedTargetBase, rawUserId)); // /data/media/0 mEmulatedDirForDirect = buildPath(mediaBase, rawUserId); @@ -148,11 +154,23 @@ public class Environment { } // /storage/sdcard0 - mExternalDirsForVold = new File[] { new File(rawExternalStorage) }; - mExternalDirsForApp = new File[] { new File(rawExternalStorage) }; + externalForVold.add(new File(rawExternalStorage)); + externalForApp.add(new File(rawExternalStorage)); // /data/media mEmulatedDirForDirect = new File(rawMediaStorage); } + + // Splice in any secondary storage paths, but only for owner + final String rawSecondaryStorage = System.getenv(ENV_SECONDARY_STORAGE); + if (!TextUtils.isEmpty(rawSecondaryStorage) && userId == UserHandle.USER_OWNER) { + for (String secondaryPath : rawSecondaryStorage.split(":")) { + externalForVold.add(new File(secondaryPath)); + externalForApp.add(new File(secondaryPath)); + } + } + + mExternalDirsForVold = externalForVold.toArray(new File[externalForVold.size()]); + mExternalDirsForApp = externalForApp.toArray(new File[externalForApp.size()]); } @Deprecated diff --git a/core/java/android/print/IPrintSpooler.aidl b/core/java/android/print/IPrintSpooler.aidl index 96b168d3908a..5f06b834ade1 100644 --- a/core/java/android/print/IPrintSpooler.aidl +++ b/core/java/android/print/IPrintSpooler.aidl @@ -48,4 +48,5 @@ oneway interface IPrintSpooler { int sequence); void writePrintJobData(in ParcelFileDescriptor fd, in PrintJobId printJobId); void setClient(IPrintSpoolerClient client); + void setPrintJobCancelling(in PrintJobId printJobId, boolean cancelling); } diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java index ec979b3a2d4d..e1a9cb7592e5 100644 --- a/core/java/android/print/PrintAttributes.java +++ b/core/java/android/print/PrintAttributes.java @@ -282,7 +282,7 @@ public final class PrintAttributes implements Parcelable { */ public static final MediaSize UNKNOWN_PORTRAIT = new MediaSize("UNKNOWN_PORTRAIT", "android", - R.string.mediasize_unknown_portrait, Integer.MAX_VALUE, 1); + R.string.mediasize_unknown_portrait, 1, Integer.MAX_VALUE); /** * Unknown media size in landscape mode. @@ -293,7 +293,7 @@ public final class PrintAttributes implements Parcelable { */ public static final MediaSize UNKNOWN_LANDSCAPE = new MediaSize("UNKNOWN_LANDSCAPE", "android", - R.string.mediasize_unknown_landscape, 1, Integer.MAX_VALUE); + R.string.mediasize_unknown_landscape, Integer.MAX_VALUE, 1); // ISO sizes diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java index ccb4f440df05..92bda4042c92 100644 --- a/core/java/android/print/PrintJobInfo.java +++ b/core/java/android/print/PrintJobInfo.java @@ -153,6 +153,9 @@ public final class PrintJobInfo implements Parcelable { /** Information about the printed document. */ private PrintDocumentInfo mDocumentInfo; + /** Whether we are trying to cancel this print job. */ + private boolean mCanceling; + /** @hide*/ public PrintJobInfo() { /* do nothing */ @@ -174,6 +177,7 @@ public final class PrintJobInfo implements Parcelable { mPageRanges = other.mPageRanges; mAttributes = other.mAttributes; mDocumentInfo = other.mDocumentInfo; + mCanceling = other.mCanceling; } private PrintJobInfo(Parcel parcel) { @@ -201,6 +205,7 @@ public final class PrintJobInfo implements Parcelable { if (parcel.readInt() == 1) { mDocumentInfo = PrintDocumentInfo.CREATOR.createFromParcel(parcel); } + mCanceling = (parcel.readInt() == 1); } /** @@ -503,6 +508,28 @@ public final class PrintJobInfo implements Parcelable { mDocumentInfo = info; } + /** + * Gets whether this print is being cancelled. + * + * @return True if the print job is being cancelled. + * + * @hide + */ + public boolean isCancelling() { + return mCanceling; + } + + /** + * Sets whether this print is being cancelled. + * + * @param cancelling True if the print job is being cancelled. + * + * @hide + */ + public void setCancelling(boolean cancelling) { + mCanceling = cancelling; + } + @Override public int describeContents() { return 0; @@ -539,6 +566,7 @@ public final class PrintJobInfo implements Parcelable { } else { parcel.writeInt(0); } + parcel.writeInt(mCanceling ? 1 : 0); } @Override @@ -556,6 +584,7 @@ public final class PrintJobInfo implements Parcelable { ? mAttributes.toString() : null)); builder.append(", documentInfo: " + (mDocumentInfo != null ? mDocumentInfo.toString() : null)); + builder.append(", cancelling: " + mCanceling); builder.append(", pages: " + (mPageRanges != null ? Arrays.toString(mPageRanges) : null)); builder.append("}"); diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index 0859fdde1744..1cb4e8d6e651 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -48,6 +48,7 @@ import java.util.Map; * <p> * To obtain a handle to the print manager do the following: * </p> + * * <pre> * PrintManager printManager = * (PrintManager) context.getSystemService(Context.PRINT_SERVICE); @@ -57,6 +58,11 @@ public final class PrintManager { private static final String LOG_TAG = "PrintManager"; + private static final boolean DEBUG = false; + + private static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 1; + private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 2; + /** @hide */ public static final int APP_ID_ANY = -2; @@ -79,18 +85,17 @@ public final class PrintManager { /** * Callback notifying that a print job state changed. - * + * * @param printJobId The print job id. */ - public void onPrintJobsStateChanged(PrintJobId printJobId); + public void onPrintJobStateChanged(PrintJobId printJobId); } /** * Creates a new instance. - * + * * @param context The current context in which to operate. * @param service The backing system service. - * * @hide */ public PrintManager(Context context, IPrintManager service, int userId, int appId) { @@ -102,14 +107,29 @@ public final class PrintManager { mHandler = new Handler(context.getMainLooper(), null, false) { @Override public void handleMessage(Message message) { - SomeArgs args = (SomeArgs) message.obj; - Context context = (Context) args.arg1; - IntentSender intent = (IntentSender) args.arg2; - args.recycle(); - try { - context.startIntentSender(intent, null, 0, 0, 0); - } catch (SendIntentException sie) { - Log.e(LOG_TAG, "Couldn't start print job config activity.", sie); + switch (message.what) { + case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: { + SomeArgs args = (SomeArgs) message.obj; + Context context = (Context) args.arg1; + IntentSender intent = (IntentSender) args.arg2; + args.recycle(); + try { + context.startIntentSender(intent, null, 0, 0, 0); + } catch (SendIntentException sie) { + Log.e(LOG_TAG, "Couldn't start print job config activity.", sie); + } + } + break; + + case MSG_NOTIFY_PRINT_JOB_STATE_CHANGED: { + SomeArgs args = (SomeArgs) message.obj; + PrintJobStateChangeListener listener = + (PrintJobStateChangeListener) args.arg1; + PrintJobId printJobId = (PrintJobId) args.arg2; + args.recycle(); + listener.onPrintJobStateChanged(printJobId); + } + break; } } }; @@ -117,10 +137,10 @@ public final class PrintManager { /** * Creates an instance that can access all print jobs. - * + * * @param userId The user id for which to get all print jobs. - * @return An instance if the caller has the permission to access - * all print jobs, null otherwise. + * @return An instance if the caller has the permission to access all print + * jobs, null otherwise. * @hide */ public PrintManager getGlobalPrintManagerForUser(int userId) { @@ -138,9 +158,8 @@ public final class PrintManager { /** * Adds a listener for observing the state of print jobs. - * + * * @param listener The listener to add. - * * @hide */ public void addPrintJobStateChangeListener(PrintJobStateChangeListener listener) { @@ -149,7 +168,7 @@ public final class PrintManager { PrintJobStateChangeListenerWrapper>(); } PrintJobStateChangeListenerWrapper wrappedListener = - new PrintJobStateChangeListenerWrapper(listener); + new PrintJobStateChangeListenerWrapper(listener, mHandler); try { mService.addPrintJobStateChangeListener(wrappedListener, mAppId, mUserId); mPrintJobStateChangeListeners.put(listener, wrappedListener); @@ -160,9 +179,8 @@ public final class PrintManager { /** * Removes a listener for observing the state of print jobs. - * + * * @param listener The listener to remove. - * * @hide */ public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) { @@ -186,11 +204,9 @@ public final class PrintManager { /** * Gets a print job given its id. - * + * * @return The print job list. - * * @see PrintJob - * * @hide */ public PrintJob getPrintJob(PrintJobId printJobId) { @@ -207,9 +223,8 @@ public final class PrintManager { /** * Gets the print jobs for this application. - * + * * @return The print job list. - * * @see PrintJob */ public List<PrintJob> getPrintJobs() { @@ -247,9 +262,9 @@ public final class PrintManager { } /** - * Creates a print job for printing a {@link PrintDocumentAdapter} with default print - * attributes. - * + * Creates a print job for printing a {@link PrintDocumentAdapter} with + * default print attributes. + * * @param printJobName A name for the new print job. * @param documentAdapter An adapter that emits the document to print. * @param attributes The default print job attributes. @@ -277,9 +292,8 @@ public final class PrintManager { /** * Gets the list of enabled print services. - * + * * @return The enabled service list or an empty list. - * * @hide */ public List<PrintServiceInfo> getEnabledPrintServices() { @@ -296,9 +310,8 @@ public final class PrintManager { /** * Gets the list of installed print services. - * + * * @return The installed service list or an empty list. - * * @hide */ public List<PrintServiceInfo> getInstalledPrintServices() { @@ -335,7 +348,8 @@ public final class PrintManager { SomeArgs args = SomeArgs.obtain(); args.arg1 = manager.mContext; args.arg2 = intent; - manager.mHandler.obtainMessage(0, args).sendToTarget(); + manager.mHandler.obtainMessage(MSG_START_PRINT_JOB_CONFIG_ACTIVITY, + args).sendToTarget(); } } } @@ -346,10 +360,21 @@ public final class PrintManager { private CancellationSignal mLayoutOrWriteCancellation; - private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - cleared in finish() + private PrintDocumentAdapter mDocumentAdapter; // Strong reference OK - + // cleared in finish() private Handler mHandler; // Strong reference OK - cleared in finish() + private LayoutSpec mLastLayoutSpec; + + private WriteSpec mLastWriteSpec; + + private boolean mStartReqeusted; + private boolean mStarted; + + private boolean mFinishRequested; + private boolean mFinished; + public PrintDocumentAdapterDelegate(PrintDocumentAdapter documentAdapter, Looper looper) { mDocumentAdapter = documentAdapter; mHandler = new MyHandler(looper); @@ -357,47 +382,102 @@ public final class PrintManager { @Override public void start() { - mHandler.sendEmptyMessage(MyHandler.MSG_START); + synchronized (mLock) { + // Started or finished - nothing to do. + if (mStartReqeusted || mFinishRequested) { + return; + } + + mStartReqeusted = true; + + doPendingWorkLocked(); + } } @Override public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes, ILayoutResultCallback callback, Bundle metadata, int sequence) { synchronized (mLock) { - if (mLayoutOrWriteCancellation != null) { - mLayoutOrWriteCancellation.cancel(); + // Start not called or finish called - nothing to do. + if (!mStartReqeusted || mFinishRequested) { + return; + } + + // Layout cancels write and overrides layout. + if (mLastWriteSpec != null) { + IoUtils.closeQuietly(mLastWriteSpec.fd); + mLastWriteSpec = null; + } + + mLastLayoutSpec = new LayoutSpec(); + mLastLayoutSpec.callback = callback; + mLastLayoutSpec.oldAttributes = oldAttributes; + mLastLayoutSpec.newAttributes = newAttributes; + mLastLayoutSpec.metadata = metadata; + mLastLayoutSpec.sequence = sequence; + + // Cancel the previous cancellable operation.When the + // cancellation completes we will do the pending work. + if (cancelPreviousCancellableOperationLocked()) { + return; } + + doPendingWorkLocked(); } - SomeArgs args = SomeArgs.obtain(); - args.arg1 = oldAttributes; - args.arg2 = newAttributes; - args.arg3 = callback; - args.arg4 = metadata; - args.argi1 = sequence; - mHandler.removeMessages(MyHandler.MSG_LAYOUT); - mHandler.obtainMessage(MyHandler.MSG_LAYOUT, args).sendToTarget(); } @Override public void write(PageRange[] pages, ParcelFileDescriptor fd, IWriteResultCallback callback, int sequence) { synchronized (mLock) { - if (mLayoutOrWriteCancellation != null) { - mLayoutOrWriteCancellation.cancel(); + // Start not called or finish called - nothing to do. + if (!mStartReqeusted || mFinishRequested) { + return; } + + // Write cancels previous writes. + if (mLastWriteSpec != null) { + IoUtils.closeQuietly(mLastWriteSpec.fd); + mLastWriteSpec = null; + } + + mLastWriteSpec = new WriteSpec(); + mLastWriteSpec.callback = callback; + mLastWriteSpec.pages = pages; + mLastWriteSpec.fd = fd; + mLastWriteSpec.sequence = sequence; + + // Cancel the previous cancellable operation.When the + // cancellation completes we will do the pending work. + if (cancelPreviousCancellableOperationLocked()) { + return; + } + + doPendingWorkLocked(); } - SomeArgs args = SomeArgs.obtain(); - args.arg1 = pages; - args.arg2 = fd; - args.arg3 = callback; - args.argi1 = sequence; - mHandler.removeMessages(MyHandler.MSG_WRITE); - mHandler.obtainMessage(MyHandler.MSG_WRITE, args).sendToTarget(); } @Override public void finish() { - mHandler.sendEmptyMessage(MyHandler.MSG_FINISH); + synchronized (mLock) { + // Start not called or finish called - nothing to do. + if (!mStartReqeusted || mFinishRequested) { + return; + } + + mFinishRequested = true; + + // When the current write or layout complete we + // will do the pending work. + if (mLastLayoutSpec != null || mLastWriteSpec != null) { + if (DEBUG) { + Log.i(LOG_TAG, "Waiting for current operation"); + } + return; + } + + doPendingWorkLocked(); + } } private boolean isFinished() { @@ -407,7 +487,49 @@ public final class PrintManager { private void doFinish() { mDocumentAdapter = null; mHandler = null; - mLayoutOrWriteCancellation = null; + synchronized (mLock) { + mLayoutOrWriteCancellation = null; + } + } + + private boolean cancelPreviousCancellableOperationLocked() { + if (mLayoutOrWriteCancellation != null) { + mLayoutOrWriteCancellation.cancel(); + if (DEBUG) { + Log.i(LOG_TAG, "Cancelling previous operation"); + } + return true; + } + return false; + } + + private void doPendingWorkLocked() { + if (mStartReqeusted && !mStarted) { + mStarted = true; + mHandler.sendEmptyMessage(MyHandler.MSG_START); + } else if (mLastLayoutSpec != null) { + mHandler.sendEmptyMessage(MyHandler.MSG_LAYOUT); + } else if (mLastWriteSpec != null) { + mHandler.sendEmptyMessage(MyHandler.MSG_WRITE); + } else if (mFinishRequested && !mFinished) { + mFinished = true; + mHandler.sendEmptyMessage(MyHandler.MSG_FINISH); + } + } + + private class LayoutSpec { + ILayoutResultCallback callback; + PrintAttributes oldAttributes; + PrintAttributes newAttributes; + Bundle metadata; + int sequence; + } + + private class WriteSpec { + IWriteResultCallback callback; + PageRange[] pages; + ParcelFileDescriptor fd; + int sequence; } private final class MyHandler extends Handler { @@ -428,47 +550,62 @@ public final class PrintManager { switch (message.what) { case MSG_START: { mDocumentAdapter.onStart(); - } break; + } + break; case MSG_LAYOUT: { - SomeArgs args = (SomeArgs) message.obj; - PrintAttributes oldAttributes = (PrintAttributes) args.arg1; - PrintAttributes newAttributes = (PrintAttributes) args.arg2; - ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3; - Bundle metadata = (Bundle) args.arg4; - final int sequence = args.argi1; - args.recycle(); + final CancellationSignal cancellation; + final LayoutSpec layoutSpec; - CancellationSignal cancellation = new CancellationSignal(); synchronized (mLock) { + layoutSpec = mLastLayoutSpec; + mLastLayoutSpec = null; + cancellation = new CancellationSignal(); mLayoutOrWriteCancellation = cancellation; } - mDocumentAdapter.onLayout(oldAttributes, newAttributes, cancellation, - new MyLayoutResultCallback(callback, sequence), metadata); - } break; + if (layoutSpec != null) { + if (DEBUG) { + Log.i(LOG_TAG, "Performing layout"); + } + mDocumentAdapter.onLayout(layoutSpec.oldAttributes, + layoutSpec.newAttributes, cancellation, + new MyLayoutResultCallback(layoutSpec.callback, + layoutSpec.sequence), layoutSpec.metadata); + } + } + break; case MSG_WRITE: { - SomeArgs args = (SomeArgs) message.obj; - PageRange[] pages = (PageRange[]) args.arg1; - ParcelFileDescriptor fd = (ParcelFileDescriptor) args.arg2; - IWriteResultCallback callback = (IWriteResultCallback) args.arg3; - final int sequence = args.argi1; - args.recycle(); + final CancellationSignal cancellation; + final WriteSpec writeSpec; - CancellationSignal cancellation = new CancellationSignal(); synchronized (mLock) { + writeSpec = mLastWriteSpec; + mLastWriteSpec = null; + cancellation = new CancellationSignal(); mLayoutOrWriteCancellation = cancellation; } - mDocumentAdapter.onWrite(pages, fd, cancellation, - new MyWriteResultCallback(callback, fd, sequence)); - } break; + if (writeSpec != null) { + if (DEBUG) { + Log.i(LOG_TAG, "Performing write"); + } + mDocumentAdapter.onWrite(writeSpec.pages, writeSpec.fd, + cancellation, new MyWriteResultCallback(writeSpec.callback, + writeSpec.fd, writeSpec.sequence)); + } + } + break; case MSG_FINISH: { + if (DEBUG) { + Log.i(LOG_TAG, "Performing finish"); + } mDocumentAdapter.onFinish(); doFinish(); - } break; + } + break; default: { throw new IllegalArgumentException("Unknown message: " @@ -533,6 +670,7 @@ public final class PrintManager { private void clearLocked() { mLayoutOrWriteCancellation = null; mCallback = null; + doPendingWorkLocked(); } } @@ -598,6 +736,7 @@ public final class PrintManager { IoUtils.closeQuietly(mFd); mCallback = null; mFd = null; + doPendingWorkLocked(); } } } @@ -605,17 +744,26 @@ public final class PrintManager { private static final class PrintJobStateChangeListenerWrapper extends IPrintJobStateChangeListener.Stub { private final WeakReference<PrintJobStateChangeListener> mWeakListener; + private final WeakReference<Handler> mWeakHandler; - public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener) { + public PrintJobStateChangeListenerWrapper(PrintJobStateChangeListener listener, + Handler handler) { mWeakListener = new WeakReference<PrintJobStateChangeListener>(listener); + mWeakHandler = new WeakReference<Handler>(handler); } @Override public void onPrintJobStateChanged(PrintJobId printJobId) { + Handler handler = mWeakHandler.get(); PrintJobStateChangeListener listener = mWeakListener.get(); - if (listener != null) { - listener.onPrintJobsStateChanged(printJobId); + if (handler != null && listener != null) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = listener; + args.arg2 = printJobId; + handler.obtainMessage(MSG_NOTIFY_PRINT_JOB_STATE_CHANGED, + args).sendToTarget(); } } } + } diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index 631a8d41c064..c5e4f2110f56 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -23,8 +23,7 @@ import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.graphics.Bitmap; @@ -69,8 +68,13 @@ public final class DocumentsContract { private DocumentsContract() { } + /** + * Intent action used to identify {@link DocumentsProvider} instances. + */ + public static final String PROVIDER_INTERFACE = "android.content.action.DOCUMENTS_PROVIDER"; + /** {@hide} */ - public static final String META_DATA_DOCUMENT_PROVIDER = "android.content.DOCUMENT_PROVIDER"; + public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME"; /** {@hide} */ public static final String ACTION_MANAGE_ROOT = "android.provider.action.MANAGE_ROOT"; @@ -559,11 +563,13 @@ public final class DocumentsContract { return false; } - final ProviderInfo info = context.getPackageManager() - .resolveContentProvider(uri.getAuthority(), PackageManager.GET_META_DATA); - if (info != null && info.metaData != null && info.metaData.containsKey( - DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) { - return true; + final Intent intent = new Intent(PROVIDER_INTERFACE); + final List<ResolveInfo> infos = context.getPackageManager() + .queryIntentContentProviders(intent, 0); + for (ResolveInfo info : infos) { + if (uri.getAuthority().equals(info.providerInfo.authority)) { + return true; + } } return false; } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 989e2871b797..6f1c6baf48ca 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2441,9 +2441,7 @@ public final class Settings { SCREEN_BRIGHTNESS_MODE, SCREEN_AUTO_BRIGHTNESS_ADJ, VIBRATE_INPUT_DEVICES, - MODE_RINGER, // moved to global MODE_RINGER_STREAMS_AFFECTED, - MUTE_STREAMS_AFFECTED, VOLUME_VOICE, VOLUME_SYSTEM, VOLUME_RING, @@ -5922,6 +5920,16 @@ public final class Settings { public static final String DEVELOPMENT_FORCE_RTL = "debug.force_rtl"; /** + * Milliseconds after screen-off after which low battery sounds will be silenced. + * + * If zero, battery sounds will always play. + * Defaults to @integer/def_low_battery_sound_timeout in SettingsProvider. + * + * @hide + */ + public static final String LOW_BATTERY_SOUND_TIMEOUT = "low_battery_sound_timeout"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -5940,7 +5948,6 @@ public final class Settings { public static final String[] SETTINGS_TO_BACKUP = { BUGREPORT_IN_POWER_MENU, STAY_ON_WHILE_PLUGGED_IN, - MODE_RINGER, AUTO_TIME, AUTO_TIME_ZONE, POWER_SOUNDS_ENABLED, diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index fd458663a13a..9d4af006258e 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -274,4 +274,11 @@ interface IWindowManager * @return The magnification spec if such or null. */ MagnificationSpec getCompatibleMagnificationSpecForWindow(in IBinder windowToken); + + /** + * Sets the current touch exploration state. + * + * @param enabled Whether touch exploration is enabled. + */ + void setTouchExplorationEnabled(boolean enabled); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index caeb1d8cfc80..01da6b333d0e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1738,47 +1738,41 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Masks for mPrivateFlags2, as generated by dumpFlags(): * - * -------|-------|-------|-------| - * PFLAG2_TEXT_ALIGNMENT_FLAGS[0] - * PFLAG2_TEXT_DIRECTION_FLAGS[0] - * 1 PFLAG2_DRAG_CAN_ACCEPT - * 1 PFLAG2_DRAG_HOVERED - * 1 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT - * 11 PFLAG2_TEXT_DIRECTION_MASK_SHIFT - * 1 1 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT - * 11 PFLAG2_LAYOUT_DIRECTION_MASK - * 11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT - * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL - * 1 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT - * 1 1 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT - * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED - * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK - * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] - * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] - * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] - * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] - * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] - * 111 PFLAG2_TEXT_DIRECTION_MASK - * 1 PFLAG2_TEXT_DIRECTION_RESOLVED - * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT - * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK - * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] - * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] - * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] - * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] - * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] - * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] - * 111 PFLAG2_TEXT_ALIGNMENT_MASK - * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED - * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT - * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK - * 11 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK - * 1 PFLAG2_HAS_TRANSIENT_STATE - * 1 PFLAG2_ACCESSIBILITY_FOCUSED - * 1 PFLAG2_ACCESSIBILITY_STATE_CHANGED - * 1 PFLAG2_VIEW_QUICK_REJECTED - * 1 PFLAG2_PADDING_RESOLVED - * -------|-------|-------|-------| + * |-------|-------|-------|-------| + * 1 PFLAG2_DRAG_CAN_ACCEPT + * 1 PFLAG2_DRAG_HOVERED + * 11 PFLAG2_LAYOUT_DIRECTION_MASK + * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL + * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED + * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] + * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] + * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] + * 111 PFLAG2_TEXT_DIRECTION_MASK + * 1 PFLAG2_TEXT_DIRECTION_RESOLVED + * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT + * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] + * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] + * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] + * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] + * 111 PFLAG2_TEXT_ALIGNMENT_MASK + * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED + * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT + * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK + * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK + * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK + * 1 PFLAG2_ACCESSIBILITY_FOCUSED + * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED + * 1 PFLAG2_VIEW_QUICK_REJECTED + * 1 PFLAG2_PADDING_RESOLVED + * 1 PFLAG2_DRAWABLE_RESOLVED + * 1 PFLAG2_HAS_TRANSIENT_STATE + * |-------|-------|-------|-------| */ /** @@ -1876,15 +1870,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; /** - * Indicates that the view is tracking some sort of transient state - * that the app should not need to be aware of, but that the framework - * should take special care to preserve. - * - * @hide - */ - static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22; - - /** * Text direction is inherited thru {@link ViewGroup} */ public static final int TEXT_DIRECTION_INHERIT = 0; @@ -2216,6 +2201,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; /** + * Indicates that the view is tracking some sort of transient state + * that the app should not need to be aware of, but that the framework + * should take special care to preserve. + */ + static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; + + /** * Group of bits indicating that RTL properties resolution is done. */ static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | @@ -2431,6 +2423,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when + * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is + * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any + * user interaction. + * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only + * has an effect when used in combination with that flag.</p> + */ + public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; + + /** + * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive * experience while also hiding the system bars. If this flag is not set, @@ -2445,7 +2447,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination * with one or both of those flags.</p> */ - public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; + public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; /** * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. @@ -7090,12 +7092,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO */ public void setImportantForAccessibility(int mode) { - final boolean oldIncludeForAccessibility = includeForAccessibility(); - if (mode != getImportantForAccessibility()) { + final int oldMode = getImportantForAccessibility(); + if (mode != oldMode) { + // If we're moving between AUTO and another state, we might not need + // to send a subtree changed notification. We'll store the computed + // importance, since we'll need to check it later to make sure. + final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO + || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; + final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; - if (oldIncludeForAccessibility != includeForAccessibility()) { + if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { notifySubtreeAccessibilityStateChangedIfNeeded(); } else { notifyViewAccessibilityStateChangedIfNeeded( @@ -8887,10 +8895,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ mPrivateFlags |= PFLAG_DRAWN; - if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { + if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { // root view becoming invisible shouldn't clear focus and accessibility focus if (getRootView() != this) { - clearFocus(); + if (hasFocus()) clearFocus(); clearAccessibilityFocus(); } } @@ -16936,7 +16944,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, - * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, and {@link #SYSTEM_UI_FLAG_IMMERSIVE}. + * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, + * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. */ public void setSystemUiVisibility(int visibility) { if (visibility != mSystemUiVisibility) { @@ -16952,7 +16961,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, - * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, and {@link #SYSTEM_UI_FLAG_IMMERSIVE}. + * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, + * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. */ public int getSystemUiVisibility() { return mSystemUiVisibility; diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 79aec904e8dc..c5a1b86c0635 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -1186,4 +1186,11 @@ public interface WindowManagerPolicy { * @return True if the window is a top level one. */ public boolean isTopLevelWindow(int windowType); + + /** + * Sets the current touch exploration state. + * + * @param enabled Whether touch exploration is enabled. + */ + public void setTouchExplorationEnabled(boolean enabled); } diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index 7e2bffa40cc8..f635eee47443 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -910,10 +910,20 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par /** * Sets the performed action that triggered this event. + * <p> + * Valid actions are defined in {@link AccessibilityNodeInfo}: + * <ul> + * <li>{@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS} + * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS} + * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_FOCUS} + * <li>{@link AccessibilityNodeInfo#ACTION_CLEAR_SELECTION} + * <li>{@link AccessibilityNodeInfo#ACTION_CLICK} + * <li>etc. + * </ul> * * @param action The action. - * * @throws IllegalStateException If called from an AccessibilityService. + * @see AccessibilityNodeInfo#performAction(int) */ public void setAction(int action) { enforceNotSealed(); diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 04ce7e2665b8..00f4adb911bc 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -91,25 +91,45 @@ public final class AccessibilityManager { boolean mIsTouchExplorationEnabled; - final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners = - new CopyOnWriteArrayList<AccessibilityStateChangeListener>(); + private final CopyOnWriteArrayList<AccessibilityStateChangeListener> + mAccessibilityStateChangeListeners = new CopyOnWriteArrayList< + AccessibilityStateChangeListener>(); + + private final CopyOnWriteArrayList<TouchExplorationStateChangeListener> + mTouchExplorationStateChangeListeners = new CopyOnWriteArrayList< + TouchExplorationStateChangeListener>(); /** - * Listener for the system accessibility state. To listen for changes to the accessibility - * state on the device, implement this interface and register it with the system by - * calling {@link AccessibilityManager#addAccessibilityStateChangeListener - * addAccessibilityStateChangeListener()}. + * Listener for the system accessibility state. To listen for changes to the + * accessibility state on the device, implement this interface and register + * it with the system by calling {@link #addAccessibilityStateChangeListener}. */ public interface AccessibilityStateChangeListener { /** - * Called back on change in the accessibility state. + * Called when the accessibility enabled state changes. * * @param enabled Whether accessibility is enabled. */ public void onAccessibilityStateChanged(boolean enabled); } + /** + * Listener for the system touch exploration state. To listen for changes to + * the touch exploration state on the device, implement this interface and + * register it with the system by calling + * {@link #addTouchExplorationStateChangeListener}. + */ + public interface TouchExplorationStateChangeListener { + + /** + * Called when the touch exploration enabled state changes. + * + * @param enabled Whether touch exploration is enabled. + */ + public void onTouchExplorationStateChanged(boolean enabled); + } + final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() { public void setState(int state) { mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget(); @@ -363,34 +383,61 @@ public final class AccessibilityManager { } /** - * Sets the current state. + * Registers a {@link TouchExplorationStateChangeListener} for changes in + * the global touch exploration state of the system. * - * @param stateFlags The state flags. + * @param listener The listener. + * @return True if successfully registered. */ - private void setState(int stateFlags) { - final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; - setAccessibilityState(accessibilityEnabled); - mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0; + public boolean addTouchExplorationStateChangeListener( + TouchExplorationStateChangeListener listener) { + return mTouchExplorationStateChangeListeners.add(listener); + } + + /** + * Unregisters a {@link TouchExplorationStateChangeListener}. + * + * @param listener The listener. + * @return True if successfully unregistered. + */ + public boolean removeTouchExplorationStateChangeListener( + TouchExplorationStateChangeListener listener) { + return mTouchExplorationStateChangeListeners.remove(listener); } /** - * Sets the enabled state. + * Sets the current state and notifies listeners, if necessary. * - * @param isEnabled The accessibility state. + * @param stateFlags The state flags. */ - private void setAccessibilityState(boolean isEnabled) { + private void setState(int stateFlags) { + final boolean enabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; + final boolean touchExplorationEnabled = + (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0; synchronized (mHandler) { - if (isEnabled != mIsEnabled) { - mIsEnabled = isEnabled; - notifyAccessibilityStateChanged(); + final boolean wasEnabled = mIsEnabled; + final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled; + + // Ensure listeners get current state from isZzzEnabled() calls. + mIsEnabled = enabled; + mIsTouchExplorationEnabled = touchExplorationEnabled; + + if (wasEnabled != enabled) { + notifyAccessibilityStateChangedLh(); + } + + if (wasTouchExplorationEnabled != touchExplorationEnabled) { + notifyTouchExplorationStateChangedLh(); } } } /** * Notifies the registered {@link AccessibilityStateChangeListener}s. + * <p> + * The caller must be locked on {@link #mHandler}. */ - private void notifyAccessibilityStateChanged() { + private void notifyAccessibilityStateChangedLh() { final int listenerCount = mAccessibilityStateChangeListeners.size(); for (int i = 0; i < listenerCount; i++) { mAccessibilityStateChangeListeners.get(i).onAccessibilityStateChanged(mIsEnabled); @@ -398,6 +445,19 @@ public final class AccessibilityManager { } /** + * Notifies the registered {@link TouchExplorationStateChangeListener}s. + * <p> + * The caller must be locked on {@link #mHandler}. + */ + private void notifyTouchExplorationStateChangedLh() { + final int listenerCount = mTouchExplorationStateChangeListeners.size(); + for (int i = 0; i < listenerCount; i++) { + mTouchExplorationStateChangeListeners.get(i) + .onTouchExplorationStateChanged(mIsTouchExplorationEnabled); + } + } + + /** * Adds an accessibility interaction connection interface for a given window. * @param windowToken The window token to which a connection is added. * @param connection The connection. diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java index 6bef78e37f9b..a9473a8df63c 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfoCache.java @@ -67,11 +67,12 @@ public class AccessibilityNodeInfoCache { if (ENABLED) { final int eventType = event.getEventType(); switch (eventType) { + case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: { + // If the active window changes, clear the cache. final int windowId = event.getWindowId(); - // If a new window, we clear the cache. if (mWindowId != windowId) { mWindowId = windowId; clear(); @@ -86,7 +87,9 @@ public class AccessibilityNodeInfoCache { refreshCachedNode(event.getSourceNodeId()); } break; case AccessibilityEvent.TYPE_VIEW_SCROLLED: { - clearSubTreeLocked(event.getSourceNodeId()); + synchronized (mLock) { + clearSubTreeLocked(event.getSourceNodeId()); + } } break; case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: { synchronized (mLock) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 2cbe0e2e63aa..5bc39f158408 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -670,7 +670,6 @@ public class WebView extends AbsoluteLayout */ @Deprecated public static void enablePlatformNotifications() { - checkThread(); getFactory().getStatics().setPlatformNotificationsEnabled(true); } @@ -683,7 +682,6 @@ public class WebView extends AbsoluteLayout */ @Deprecated public static void disablePlatformNotifications() { - checkThread(); getFactory().getStatics().setPlatformNotificationsEnabled(false); } @@ -1691,7 +1689,6 @@ public class WebView extends AbsoluteLayout * @param enabled whether to enable web contents debugging */ public static void setWebContentsDebuggingEnabled(boolean enabled) { - checkThread(); getFactory().getStatics().setWebContentsDebuggingEnabled(enabled); } @@ -1704,7 +1701,6 @@ public class WebView extends AbsoluteLayout */ @Deprecated public static synchronized PluginList getPluginList() { - checkThread(); return new PluginList(); } @@ -2058,13 +2054,18 @@ public class WebView extends AbsoluteLayout return WebViewFactory.getProvider(); } - private static void checkThread() { - if (Looper.myLooper() != Looper.getMainLooper()) { + private final Looper mWebViewThread = Looper.myLooper(); + + private void checkThread() { + // Ignore mWebViewThread == null because this can be called during in the super class + // constructor, before this class's own constructor has even started. + if (mWebViewThread != null && Looper.myLooper() != mWebViewThread) { Throwable throwable = new Throwable( - "Warning: A WebView method was called on thread '" + + "A WebView method was called on thread '" + Thread.currentThread().getName() + "'. " + - "All WebView methods must be called on the UI thread. " + - "Future versions of WebView may not support use on other threads."); + "All WebView methods must be called on the same thread. " + + "(Expected Looper " + mWebViewThread + " called on " + Looper.myLooper() + + ", FYI main Looper is " + Looper.getMainLooper() + ")"); Log.w(LOGTAG, Log.getStackTraceString(throwable)); StrictMode.onWebViewMethodCalledOnWrongThread(throwable); diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 0fd4e33a43d1..16daba05c9b7 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -28,19 +28,6 @@ import android.util.Log; * @hide */ public final class WebViewFactory { - private static final boolean DEFAULT_TO_EXPERIMENTAL_WEBVIEW = true; - // REMEMBER: property names must be <= 31 chars total. - private static final String EXPERIMENTAL_PROPERTY_DEFAULT_OFF = "persist.sys.webview.exp"; - private static final String EXPERIMENTAL_PROPERTY_DEFAULT_ON = - "persist.sys.webview." + Build.ID; - - // Modify the persisted property name when the new webview is on-by-default, so that any user - // setting override only lives as long as that build. - private static final String LONG_PROPERTY_NAME = DEFAULT_TO_EXPERIMENTAL_WEBVIEW ? - EXPERIMENTAL_PROPERTY_DEFAULT_ON : EXPERIMENTAL_PROPERTY_DEFAULT_OFF; - private static final String WEBVIEW_EXPERIMENTAL_PROPERTY = - LONG_PROPERTY_NAME.length() > SystemProperties.PROP_NAME_MAX ? - LONG_PROPERTY_NAME.substring(0, SystemProperties.PROP_NAME_MAX) : LONG_PROPERTY_NAME; private static final String FORCE_PROVIDER_PROPERTY = "webview.force_provider"; private static final String FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM = "chromium"; @@ -73,32 +60,25 @@ public final class WebViewFactory { private static final Object sProviderLock = new Object(); public static boolean isExperimentalWebViewAvailable() { - try { - // Pass false so we don't initialize the class at this point, as this will be wasted if - // it's not enabled. - Class.forName(CHROMIUM_WEBVIEW_FACTORY, false, WebViewFactory.class.getClassLoader()); - return true; - } catch (ClassNotFoundException e) { - return false; - } + // TODO: Remove callers of this method then remove it. + return false; // Hide the toggle in Developer Settings. } /** @hide */ public static void setUseExperimentalWebView(boolean enable) { - SystemProperties.set(WEBVIEW_EXPERIMENTAL_PROPERTY, enable ? "true" : "false"); - Log.i(LOGTAG, "Use Experimental WebView changed: " - + SystemProperties.get(WebViewFactory.WEBVIEW_EXPERIMENTAL_PROPERTY, "")); + // TODO: Remove callers of this method then remove it. } /** @hide */ public static boolean useExperimentalWebView() { - return SystemProperties.getBoolean(WEBVIEW_EXPERIMENTAL_PROPERTY, - DEFAULT_TO_EXPERIMENTAL_WEBVIEW); + // TODO: Remove callers of this method then remove it. + return isChromiumWebViewEnabled(); } /** @hide */ public static boolean isUseExperimentalWebViewSet() { - return !SystemProperties.get(WEBVIEW_EXPERIMENTAL_PROPERTY).isEmpty(); + // TODO: Remove callers of this method then remove it. + return false; // User has not modifed Developer Settings } static WebViewFactoryProvider getProvider() { @@ -140,21 +120,20 @@ public final class WebViewFactory { // We allow a system property to specify that we should use the experimental Chromium powered // WebView. This enables us to switch between implementations at runtime. - private static boolean isExperimentalWebViewEnabled() { - if (!isExperimentalWebViewAvailable()) return false; + private static boolean isChromiumWebViewEnabled() { String forceProviderName = SystemProperties.get(FORCE_PROVIDER_PROPERTY); - if (forceProviderName.isEmpty()) return useExperimentalWebView(); + if (forceProviderName.isEmpty()) return true; Log.i(LOGTAG, String.format("Provider overridden by property: %s=%s", FORCE_PROVIDER_PROPERTY, forceProviderName)); if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CHROMIUM)) return true; if (forceProviderName.equals(FORCE_PROVIDER_PROPERTY_VALUE_CLASSIC)) return false; Log.e(LOGTAG, String.format("Unrecognized provider: %s", forceProviderName)); - return useExperimentalWebView(); + return true; } private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException { - if (isExperimentalWebViewEnabled()) { + if (isChromiumWebViewEnabled()) { return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY); } else { return (Class<WebViewFactoryProvider>) Class.forName(DEFAULT_WEBVIEW_FACTORY); diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 3e53b91bd0b0..9e35a236fdec 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -27,6 +27,7 @@ import android.graphics.Matrix; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.Xfermode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -73,6 +74,7 @@ public class ImageView extends View { // these are applied to the drawable private ColorFilter mColorFilter; + private Xfermode mXfermode; private int mAlpha = 255; private int mViewAlphaScale = 256; private boolean mColorMod = false; @@ -1125,6 +1127,18 @@ public class ImageView extends View { } /** + * @hide Candidate for future API inclusion + */ + public final void setXfermode(Xfermode mode) { + if (mXfermode != mode) { + mXfermode = mode; + mColorMod = true; + applyColorMod(); + invalidate(); + } + } + + /** * Returns the active color filter for this ImageView. * * @return the active color filter for this ImageView @@ -1200,6 +1214,7 @@ public class ImageView extends View { if (mDrawable != null && mColorMod) { mDrawable = mDrawable.mutate(); mDrawable.setColorFilter(mColorFilter); + mDrawable.setXfermode(mXfermode); mDrawable.setAlpha(mAlpha * mViewAlphaScale >> 8); } } diff --git a/core/java/com/android/internal/inputmethod/InputMethodRoot.java b/core/java/com/android/internal/inputmethod/InputMethodRoot.java new file mode 100644 index 000000000000..40a424bcdd92 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/InputMethodRoot.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 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. + */ + +package com.android.internal.inputmethod; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +public class InputMethodRoot extends LinearLayout { + + private View mNavigationGuard; + + public InputMethodRoot(Context context) { + this(context, null); + } + + public InputMethodRoot(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public InputMethodRoot(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs); + } + + @Override + protected boolean fitSystemWindows(Rect insets) { + if (mNavigationGuard == null) { + mNavigationGuard = findViewById(com.android.internal.R.id.navigationGuard); + } + if (mNavigationGuard == null) { + return super.fitSystemWindows(insets); + } + ViewGroup.LayoutParams lp = mNavigationGuard.getLayoutParams(); + lp.height = insets.bottom; + mNavigationGuard.setLayoutParams(lp); + return true; + } +} diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 04351da6dff7..73d34c315c24 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -322,6 +322,9 @@ public class ZygoteInit { // Restore default. runtime.setTargetHeapUtilization(defaultUtilization); + // Fill in dex caches with classes, fields, and methods brought in by preloading. + runtime.preloadDexCaches(); + Debug.stopAllocCounting(); // Bring back root. We'll need it later. diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java index 23ed019d3954..44e7ec1ac005 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java +++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java @@ -160,8 +160,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter public View getItemView(final MenuItemImpl item, View convertView, ViewGroup parent) { View actionView = item.getActionView(); if (actionView == null || item.hasCollapsibleActionView()) { - // Don't recycle existing item views for action buttons; it interferes with transitions. - actionView = super.getItemView(item, null, parent); + actionView = super.getItemView(item, convertView, parent); } actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java index ccedf63ca9d5..071193cef162 100644 --- a/core/java/com/android/internal/widget/SubtitleView.java +++ b/core/java/com/android/internal/widget/SubtitleView.java @@ -180,7 +180,9 @@ public class SubtitleView extends View { mInnerPaddingX = (int) (size * INNER_PADDING_RATIO + 0.5f); mHasMeasurements = false; - forceLayout(); + + requestLayout(); + invalidate(); } } @@ -189,7 +191,9 @@ public class SubtitleView extends View { mTextPaint.setTypeface(typeface); mHasMeasurements = false; - forceLayout(); + + requestLayout(); + invalidate(); } } @@ -198,7 +202,9 @@ public class SubtitleView extends View { mAlignment = textAlignment; mHasMeasurements = false; - forceLayout(); + + requestLayout(); + invalidate(); } } diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 0d757f75bd58..da6219fcfeb1 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -514,6 +514,9 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi } SkAutoTUnref<SkData> data(SkData::NewFromFD(descriptor)); + if (data.get() == NULL) { + return nullObjectReturn("NewFromFD failed in nativeDecodeFileDescriptor"); + } SkAutoTUnref<SkMemoryStream> stream(new SkMemoryStream(data)); /* Allow purgeable iff we own the FD, i.e., in the puregeable and diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 15e1d0f6494e..768fefced915 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -773,7 +773,8 @@ android:description="@string/permdesc_bluetoothAdmin" android:label="@string/permlab_bluetoothAdmin" /> - <!-- Allows applications to pair bluetooth devices without user interaction --> + <!-- Allows applications to pair bluetooth devices without user interaction. + This is not available to third party applications. --> <permission android:name="android.permission.BLUETOOTH_PRIVILEGED" android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK" android:protectionLevel="system|signature" @@ -1110,7 +1111,8 @@ android:description="@string/permdesc_use_sip" android:label="@string/permlab_use_sip" /> - <!-- Allows an application to request CallHandlerService implementations. --> + <!-- Allows an application to request CallHandlerService implementations. + @hide --> <permission android:name="android.permission.BIND_CALL_SERVICE" android:permissionGroup="android.permission-group.PHONE_CALLS" android:protectionLevel="system|signature" @@ -1956,13 +1958,15 @@ <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService} or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only - the system can bind to it. --> + the system can bind to it. + @hide --> <permission android:name="android.permission.BIND_NFC_SERVICE" android:label="@string/permlab_bindNfcService" android:description="@string/permdesc_bindNfcService" android:protectionLevel="signature" /> - <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it. --> + <!-- Must be required by the PrintSpooler to ensure that only the system can bind to it. + @hide --> <permission android:name="android.permission.BIND_PRINT_SPOOLER_SERVICE" android:label="@string/permlab_bindPrintSpoolerService" android:description="@string/permdesc_bindPrintSpoolerService" @@ -1997,7 +2001,8 @@ android:protectionLevel="signature" /> <!-- Required to add or remove another application as a device admin. - <p/>Not for use by third-party applications. --> + <p>Not for use by third-party applications. + @hide --> <permission android:name="android.permission.MANAGE_DEVICE_ADMINS" android:label="@string/permlab_manageDeviceAdmins" android:description="@string/permdesc_manageDeviceAdmins" diff --git a/core/res/res/drawable-hdpi/stat_sys_gps_on.png b/core/res/res/drawable-hdpi/stat_sys_gps_on.png Binary files differindex cb8a1e81d8ea..e0f77402c35b 100644 --- a/core/res/res/drawable-hdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-hdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-ldpi/stat_sys_gps_on.png b/core/res/res/drawable-ldpi/stat_sys_gps_on.png Binary files differindex 8915c59ae7b5..77776f50dbf4 100644 --- a/core/res/res/drawable-ldpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-ldpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-mdpi/stat_sys_gps_on.png b/core/res/res/drawable-mdpi/stat_sys_gps_on.png Binary files differindex 2c98972e5ac2..311a1de3799b 100644 --- a/core/res/res/drawable-mdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-mdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png Binary files differindex a7408d492c8c..8a6edfb5418d 100644 --- a/core/res/res/drawable-xhdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-xhdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png Binary files differindex 81fb04ad8f52..063f61416206 100755 --- a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png +++ b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png diff --git a/core/res/res/drawable/edit_text_holo_light.xml b/core/res/res/drawable/edit_text_holo_light.xml index 5bdcbd9c8b9d..9e913e97f78a 100644 --- a/core/res/res/drawable/edit_text_holo_light.xml +++ b/core/res/res/drawable/edit_text_holo_light.xml @@ -27,7 +27,7 @@ <item android:state_window_focused="false" android:state_enabled="true" android:drawable="@drawable/textfield_default_holo_light" /> <item android:state_window_focused="false" android:state_enabled="false" android:drawable="@drawable/textfield_disabled_holo_light" /> <item android:state_enabled="true" android:state_focused="true" android:drawable="@drawable/textfield_activated_holo_light" /> - <iten android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_focused_holo_light" /> + <item android:state_enabled="true" android:state_activated="true" android:drawable="@drawable/textfield_focused_holo_light" /> <item android:state_enabled="true" android:drawable="@drawable/textfield_default_holo_light" /> <item android:state_focused="true" android:drawable="@drawable/textfield_disabled_focused_holo_light" /> <item android:drawable="@drawable/textfield_disabled_holo_light" /> diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml index f80d62876c26..00a3990ba430 100644 --- a/core/res/res/layout/input_method.xml +++ b/core/res/res/layout/input_method.xml @@ -18,7 +18,7 @@ */ --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" +<com.android.internal.inputmethod.InputMethodRoot xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parentPanel" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -52,4 +52,9 @@ android:layout_height="wrap_content" android:visibility="gone"> </FrameLayout> -</LinearLayout> + + <View android:id="@+id/navigationGuard" + android:layout_width="match_parent" + android:layout_height="0dp" + android:background="@+color/input_method_navigation_guard"/> +</com.android.internal.inputmethod.InputMethodRoot> diff --git a/core/res/res/values-mcc214/config.xml b/core/res/res/values-mcc214/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc214/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc216/config.xml b/core/res/res/values-mcc216/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc216/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc219/config.xml b/core/res/res/values-mcc219/config.xml index 80f4e587c1a5..7ae82fa91c95 100644 --- a/core/res/res/values-mcc219/config.xml +++ b/core/res/res/values-mcc219/config.xml @@ -29,7 +29,4 @@ <item>"96"</item> </string-array> - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - </resources> diff --git a/core/res/res/values-mcc222/config.xml b/core/res/res/values-mcc222/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc222/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc226/config.xml b/core/res/res/values-mcc226/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc226/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc228/config.xml b/core/res/res/values-mcc228/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc228/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc230/config.xml b/core/res/res/values-mcc230/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc230/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc231/config.xml b/core/res/res/values-mcc231/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc231/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc232/config.xml b/core/res/res/values-mcc232/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc232/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc234/config.xml b/core/res/res/values-mcc234/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc234/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc238/config.xml b/core/res/res/values-mcc238/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc238/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc240/config.xml b/core/res/res/values-mcc240/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc240/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc242/config.xml b/core/res/res/values-mcc242/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc242/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc244/config.xml b/core/res/res/values-mcc244/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc244/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc246/config.xml b/core/res/res/values-mcc246/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc246/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc247/config.xml b/core/res/res/values-mcc247/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc247/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc248/config.xml b/core/res/res/values-mcc248/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc248/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc260/config.xml b/core/res/res/values-mcc260/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc260/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc262/config.xml b/core/res/res/values-mcc262/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc262/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc268/config.xml b/core/res/res/values-mcc268/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc268/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc270/config.xml b/core/res/res/values-mcc270/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc270/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc272/config.xml b/core/res/res/values-mcc272/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc272/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc274/config.xml b/core/res/res/values-mcc274/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc274/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc278/config.xml b/core/res/res/values-mcc278/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc278/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc280/config.xml b/core/res/res/values-mcc280/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc280/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc284/config.xml b/core/res/res/values-mcc284/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc284/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc286/config.xml b/core/res/res/values-mcc286/config.xml index f73a5236e2c3..d99d0516eb21 100644 --- a/core/res/res/values-mcc286/config.xml +++ b/core/res/res/values-mcc286/config.xml @@ -61,7 +61,4 @@ to enable use of the new Release 9 tables for Indic languages. --> <!-- <integer-array name="config_sms_enabled_locking_shift_tables"></integer-array> --> - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - </resources> diff --git a/core/res/res/values-mcc293/config.xml b/core/res/res/values-mcc293/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc293/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc294/config.xml b/core/res/res/values-mcc294/config.xml deleted file mode 100644 index 8d6d3b1997f2..000000000000 --- a/core/res/res/values-mcc294/config.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - - <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> - -</resources> diff --git a/core/res/res/values-mcc202/config.xml b/core/res/res/values-mcc310/config.xml index 8d6d3b1997f2..df398f9aab32 100644 --- a/core/res/res/values-mcc202/config.xml +++ b/core/res/res/values-mcc310/config.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> + <bool name="config_safe_media_volume_enabled">false</bool> </resources> diff --git a/core/res/res/values-mcc204/config.xml b/core/res/res/values-mcc311/config.xml index 8d6d3b1997f2..df398f9aab32 100644 --- a/core/res/res/values-mcc204/config.xml +++ b/core/res/res/values-mcc311/config.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> + <bool name="config_safe_media_volume_enabled">false</bool> </resources> diff --git a/core/res/res/values-mcc206/config.xml b/core/res/res/values-mcc312/config.xml index 8d6d3b1997f2..df398f9aab32 100644 --- a/core/res/res/values-mcc206/config.xml +++ b/core/res/res/values-mcc312/config.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> + <bool name="config_safe_media_volume_enabled">false</bool> </resources> diff --git a/core/res/res/values-mcc208/config.xml b/core/res/res/values-mcc313/config.xml index 8d6d3b1997f2..df398f9aab32 100644 --- a/core/res/res/values-mcc208/config.xml +++ b/core/res/res/values-mcc313/config.xml @@ -20,6 +20,6 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">true</bool> + <bool name="config_safe_media_volume_enabled">false</bool> </resources> diff --git a/core/res/res/values-mcc314/config.xml b/core/res/res/values-mcc314/config.xml new file mode 100644 index 000000000000..df398f9aab32 --- /dev/null +++ b/core/res/res/values-mcc314/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Whether safe headphone volume is enabled or not (country specific). --> + <bool name="config_safe_media_volume_enabled">false</bool> + +</resources> diff --git a/core/res/res/values-mcc315/config.xml b/core/res/res/values-mcc315/config.xml new file mode 100644 index 000000000000..df398f9aab32 --- /dev/null +++ b/core/res/res/values-mcc315/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Whether safe headphone volume is enabled or not (country specific). --> + <bool name="config_safe_media_volume_enabled">false</bool> + +</resources> diff --git a/core/res/res/values-mcc316/config.xml b/core/res/res/values-mcc316/config.xml new file mode 100644 index 000000000000..df398f9aab32 --- /dev/null +++ b/core/res/res/values-mcc316/config.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2012, 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Whether safe headphone volume is enabled or not (country specific). --> + <bool name="config_safe_media_volume_enabled">false</bool> + +</resources> diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 81ee3af51900..28e7af7ac8d9 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -78,6 +78,7 @@ <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable> <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable> + <color name="input_method_navigation_guard">#ff000000</color> <!-- For date picker widget --> <drawable name="selected_day_background">#ff0092f4</drawable> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 429a8a4f8b10..56c4d9eb2064 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1148,7 +1148,7 @@ <bool name="config_useDevInputEventForAudioJack">false</bool> <!-- Whether safe headphone volume is enabled or not (country specific). --> - <bool name="config_safe_media_volume_enabled">false</bool> + <bool name="config_safe_media_volume_enabled">true</bool> <!-- Set to true if the wifi display supports compositing content stored in gralloc protected buffers. For this to be true, there must exist diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index ad9144c5008d..adcb3fb2db3b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -105,6 +105,7 @@ <java-symbol type="id" name="month" /> <java-symbol type="id" name="month_name" /> <java-symbol type="id" name="name" /> + <java-symbol type="id" name="navigationGuard" /> <java-symbol type="id" name="next" /> <java-symbol type="id" name="next_button" /> <java-symbol type="id" name="new_app_action" /> @@ -1441,6 +1442,7 @@ <java-symbol type="bool" name="config_wimaxEnabled" /> <java-symbol type="bool" name="show_ongoing_ime_switcher" /> <java-symbol type="color" name="config_defaultNotificationColor" /> + <java-symbol type="color" name="input_method_navigation_guard" /> <java-symbol type="drawable" name="ic_notification_ime_default" /> <java-symbol type="drawable" name="ic_notify_wifidisplay" /> <java-symbol type="drawable" name="ic_menu_refresh" /> diff --git a/docs/html/distribute/googleplay/spotlight/games.jd b/docs/html/distribute/googleplay/spotlight/games.jd index 4e356dbe7afa..1fbc03f6985b 100644 --- a/docs/html/distribute/googleplay/spotlight/games.jd +++ b/docs/html/distribute/googleplay/spotlight/games.jd @@ -102,7 +102,7 @@ going back to our other titles, adding the features to them as well."</p> width: 78px; float: left; margin: 12px 20px 30px 20px;" - src="//lh5.ggpht.com/l20dR2HYLV8vECoC35q_0NdfaAGTe4lZIFy_wCJRDqZjeQqSgneLRpXi3qOnnCaLXA=w124"> + src="//lh4.ggpht.com/Q7mQJsdhulW4_s039R9aaRhQkGnyzLkhF00j5EnyhHOivijnyi7P7b5A8qG0xk1r-jQ=w124"> <div style="list-style: none;height:100%; float: right; diff --git a/docs/html/distribute/googleplay/spotlight/tablets.jd b/docs/html/distribute/googleplay/spotlight/tablets.jd index cfea29a3974e..7a987555b1b5 100644 --- a/docs/html/distribute/googleplay/spotlight/tablets.jd +++ b/docs/html/distribute/googleplay/spotlight/tablets.jd @@ -17,7 +17,90 @@ offering. </p> expand their offering to include Android tablets.</p> -<div style="margin-bottom:2em;"><!-- START STORY --> +<div style="margin-bottom:2em;" id="rememberthemilk"><!-- START STORY --> + +<h3>Remember The Milk: Lifting installs with tablet design</h3> + + <img alt="" class="screenshot thumbnail" style="-webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px height:78px; + width: 78px; + float: left; + margin: 12px 20px 9px 20px;" src= + "//lh3.ggpht.com/xmnal18taauP2mjQFEhr1PhcItQ_W32IRuaD86IoL2U_4E-mfeKiliKtkISgOuA6Ln9n=w124"> + + <div style="list-style: none;height:100%; + float: right; + border-top: 1px solid #9C0; + width: 220px; + margin: 4px 20px;padding: .5em;"> + + + <h5>About the app</h5> + + + <ul> + <li><a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM">Remember The Milk</a></li> + <li>A feature-packed to-do list app; never forget the milk (or anything else) again</li> + </ul> + + <h5>Tablet Results</h5> + + <ul> + <li>83% jump in tablet installs following update </li> + <li>Nexus 7 is most popular Android device for app </li> + <li>Single APK for phones and tablets</li> + </ul> + + <div style="padding:.5em 0 0 1em;"> + <a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM"> + <img alt="Android app on Google Play" + src="//developer.android.com/images/brand/en_generic_rgb_wo_45.png" /> + </a> + + </div> + </div> + + <div style="line-height:1.4em;"> + <p style="margin-top:0;margin-bottom:12px;">When the Android tablet guidelines + came out in 2012, the team at Remember The Milk had already been thinking about + a redesign for their <a href="//play.google.com/store/apps/details?id=com.rememberthemilk.MobileRTM">feature-packed + to-do list app</a>. Omar Kilani, Co-founder of Remember The Milk, explains how + <a href="//blog.rememberthemilk.com/2013/04/the-all-new-remember-the-milk-for-android-and-tablets-too/">updating</a> + their app to meet the tablet guidelines lead to an 83% jump in tablet installs: </p> + + <p>“We took this as an opportunity to think about how we were going to approach + Android tablets differently from a user experience perspective. The guidelines + were a helpful resource, and with the extra screen real estate tablets afford, + users have the opportunity to see all of their data in context and drill down + on more items. All of this is accomplished using a single APK on Play, even though + the phone and tablet versions each capture completely different use cases for us.”</p> + + <p>“In the month after updating, we saw our tablet installs on Google Play jump 83%, + and the Nexus 7 is now the most popular Android device amongst our users. For us, + designing for tablets was an investment that has really paid off.”</p> + + <p>The team also came out with a number of other goodies — including a new set of + widgets and richer notifications, and more ways to provide an immersive experience + for their users.</p> + </div> + + <div style="clear:both;margin-top:30px;width:auto;"> + + <img src="{@docRoot}images/distribute/rememberthemilk.png"> + + <div style="width:600px;margin-top:0px;padding:0 90px;"> + <p class="image-caption"><span style="font-weight:500;">Tablet redesign led to lift + in installs</span>: Following the redesign of the Android app, in part to meet the tablet + design criteria, Remember The Milk saw an 83% increase in tablet installs.</p> + </div> + + </div> + +</div> <!-- END STORY --> + + +<div style="margin-bottom:2em;" id="mint"><!-- START STORY --> <h3>Mint: More screen real estate = more engagement</h3> @@ -96,7 +179,7 @@ phone apps serve as great complements to each other."</p> <div style="clear:both;margin-top:40px;width:auto;"> - <a href=""><img src="{@docRoot}images/distribute/mint.png"></a> + <img src="{@docRoot}images/distribute/mint.png"> <div style="width:600px;margin-top:0px;padding:0 90px;"> <p class="image-caption"><span style="font-weight:500;">Making the most of tablet screens</span>: Mint used the extra screen area on tablets to offer quick access to additional tools and information.</p> @@ -184,7 +267,7 @@ longer and spend more while they’re there, you have a recipe for success.”</ <div style="clear:both;margin-top:40px;width:auto;"> - <a href=""><img src="{@docRoot}images/distribute/tinyvillage.png"></a> + <img src="{@docRoot}images/distribute/tinyvillage.png"> <div style="width:600px;margin-top:0px;padding:0 90px;"> <p class="image-caption"><span style="font-weight:500;">More monetization @@ -268,7 +351,7 @@ tablets continues to pay off.”</p> <div style="clear:both;margin-top:40px;width:auto;"> - <a href=""><img src="{@docRoot}images/distribute/instapaper.png"></a> + <img src="{@docRoot}images/distribute/instapaper.png"> <div style="width:600px;margin-top:0px;padding:0 90px;"> <p class="image-caption"><span style="font-weight:500;">Popular with diff --git a/docs/html/images/distribute/rememberthemilk.png b/docs/html/images/distribute/rememberthemilk.png Binary files differnew file mode 100644 index 000000000000..b170cf36f561 --- /dev/null +++ b/docs/html/images/distribute/rememberthemilk.png diff --git a/docs/html/training/articles/security-tips.jd b/docs/html/training/articles/security-tips.jd index 1ac56b9a77c1..54aebac72502 100644 --- a/docs/html/training/articles/security-tips.jd +++ b/docs/html/training/articles/security-tips.jd @@ -553,7 +553,7 @@ android.content.Context#sendOrderedBroadcast sendOrderedBroadcast()}, or an explicit intent to a specific application component.</p> <p>Note that ordered broadcasts can be “consumed” by a recipient, so they -may not be delivered to all applications. If you are sending an intent that muse be delivered +may not be delivered to all applications. If you are sending an intent that must be delivered to a specific receiver, then you must use an explicit intent that declares the receiver by nameintent.</p> diff --git a/docs/html/training/basics/fragments/fragment-ui.jd b/docs/html/training/basics/fragments/fragment-ui.jd index db3119b252c2..14469bf0380f 100644 --- a/docs/html/training/basics/fragments/fragment-ui.jd +++ b/docs/html/training/basics/fragments/fragment-ui.jd @@ -122,11 +122,11 @@ public class MainActivity extends FragmentActivity { return; } - // Create an instance of ExampleFragment + // Create a new Fragment to be placed in the activity layout HeadlinesFragment firstFragment = new HeadlinesFragment(); - // In case this activity was started with special instructions from an Intent, - // pass the Intent's extras to the fragment as arguments + // In case this activity was started with special instructions from an + // Intent, pass the Intent's extras to the fragment as arguments firstFragment.setArguments(getIntent().getExtras()); // Add the fragment to the 'fragment_container' FrameLayout diff --git a/docs/html/training/beam-files/index.jd b/docs/html/training/beam-files/index.jd new file mode 100644 index 000000000000..71550924a8f8 --- /dev/null +++ b/docs/html/training/beam-files/index.jd @@ -0,0 +1,61 @@ +page.title=Sharing Files with NFC + +trainingnavtop=true +startpage=true + + +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>Dependencies and prerequisites</h2> +<ul> + <li>Android 4.1 (API Level 16) or higher</li> + <li>At least two NFC-enabled Android devices (NFC is not supported in the emulator)</li> +</ul> + +<h2>You should also read</h2> +<ul> + <li> + <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal" + >Using the External Storage</a> + </li> +</ul> + +</div> +</div> + +<p> + Android allows you to transfer large files between devices using the Android Beam file transfer + feature. This feature has a simple API and allows users to start the transfer process by simply + touching devices. In response, Android Beam file transfer automatically copies files from one + device to the other and notifies the user when it's finished. +</p> +<p> + While the Android Beam file transfer API handles large amounts of data, the Android Beam NDEF + transfer API introduced in Android 4.0 (API level 14) handles small amounts of data such as + URIs or other small messages. In addition, Android Beam is only one of the features available + in the Android NFC framework, which allows you to read NDEF messages from NFC tags. To learn + more about Android Beam, see the topic + <a href="{@docRoot}guide/topics/connectivity/nfc/nfc.html#p2p" + >Beaming NDEF Messages to Other Devices</a>. To learn more about the NFC framework, see the + <a href="{@docRoot}guide/topics/connectivity/nfc/index.html" + >Near Field Communication</a> API guide. +</p> +<h2>Lessons</h2> +<dl> + <dt> + <b><a href="send-files.html">Sending Files to Another Device</a></b> + </dt> + <dd>Learn how to set up your app to send files to another device.</dd> + + <dt> + <b><a href="receive-files.html">Receiving Files from Another Device</a></b> + </dt> + <dd> + Learn how to set up your app to receive files sent by another device. + </dd> +</dl> + + diff --git a/docs/html/training/beam-files/receive-files.jd b/docs/html/training/beam-files/receive-files.jd new file mode 100644 index 000000000000..06136125e8a6 --- /dev/null +++ b/docs/html/training/beam-files/receive-files.jd @@ -0,0 +1,313 @@ +page.title=Receiving Files from Another Device + +trainingnavtop=true +@jd:body + +<div id="tb-wrapper"> +<div id="tb"> + +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#IntentFilter">Respond to a Request to Display Data</a></li> + <li><a href="#RequestPermissions">Request File Permissions</a></li> + <li><a href="#GetFilePath">Get the Directory for Copied Files</a></li> +</ol> +<h2>You should also read</h2> +<ul> + <li> + <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#ContentURIs" + >Content URIs</a> + </li> + <li> + <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> + </li> + <li> + <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a> + </li> + <li> + <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal" + >Using the External Storage</a> + </li> +</ul> + +</div> +</div> + +<p> + Android Beam file transfer copies files to a special directory on the receiving device. It also + scans the copied files using the Android Media Scanner and adds entries for media files to + the {@link android.provider.MediaStore} provider. This lesson shows you how to respond when the + file copy is complete, and how to locate the copied files on the receiving device. +</p> +<h2 id="IntentFilter">Respond to a Request to Display Data</h2> +<p> + When Android Beam file transfer finishes copying files to the receiving device, it posts a + notification containing an {@link android.content.Intent} with the action + {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}, the MIME type of the first file that + was transferred, and a URI that points to the first file. When the user clicks the notification, + this intent is sent out to the system. To have your app respond to this intent, add an + <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html" + ><intent-filter></a></code> element for the + <code><a href="{@docRoot}guide/topics/manifest/activity-element.html" + ><activity></a></code> element of the {@link android.app.Activity} that should respond. + In the <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html" + ><intent-filter></a></code> element, add the following child elements: +</p> +<dl> + <dt> + <code><a href="{@docRoot}guide/topics/manifest/action-element.html" + ><action android:name="android.intent.action.VIEW" /></a></code> + </dt> + <dd> + Matches the {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent sent from the + notification. + </dd> + <dt> + <code><a href="{@docRoot}guide/topics/manifest/category-element.html" + ><category android:name="android.intent.category.CATEGORY_DEFAULT" /></a></code> + </dt> + <dd> + Matches an {@link android.content.Intent} that doesn't have an explicit category. + </dd> + <dt> + <code><a href="{@docRoot}guide/topics/manifest/data-element.html" + ><data android:mimeType="<i>mime-type</i>" /></a></code> + </dt> + <dd> + Matches a MIME type. Specify only those MIME types that your app can handle. + </dd> +</dl> +<p> + For example, the following snippet shows you how to add an intent filter that + triggers the activity <code>com.example.android.nfctransfer.ViewActivity</code>: +</p> +<pre> + <activity + android:name="com.example.android.nfctransfer.ViewActivity" + android:label="Android Beam Viewer" > + ... + <intent-filter> + <action android:name="android.intent.action.VIEW"/> + <category android:name="android.intent.category.DEFAULT"/> + ... + </intent-filter> + </activity> +</pre> +<p class="note"> + <strong>Note:</strong> Android Beam file transfer is not the only source of an + {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent. Other apps on the receiving + device can also send an {@link android.content.Intent} with this action. + Handling this situation is discussed in the section <a href="#GetDirectory" + >Get the directory from a content URI</a>. +</p> +<h2 id="RequestPermissions">Request File Permissions</h2> +<p> + To read files that Android Beam file transfer copies to the device, request the permission + {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE}. For example: +</p> +<pre> + <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /></pre> +<p> + If you want to copy transferred files to your app's own storage area, request the permission + {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE} instead. + {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE} includes + {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE}. +</p> +<p class="note"> + <strong>Note:</strong> As of Android 4.2.2 (API level 17), the permission + {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE} is + only enforced if the user chooses to do so. Future versions of the platform may require this + permission in all cases. To ensure forward compatibility, request the permission now, before it + becomes required. +</p> +<p> + Since your app has control over its internal storage area, you don't need to request + write permission to copy a transferred file to your internal storage area. +</p> +<h2 id="GetFilePath">Get the Directory for Copied Files</h2> +<p> + Android Beam file transfer copies all the files in a single transfer to one directory + on the receiving device. The URI in the content {@link android.content.Intent} sent by the + Android Beam file transfer notification points to the first transferred file. However, your + app may also receive an {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent from a + source other than Android Beam file transfer. To determine how you should handle the incoming + {@link android.content.Intent}, you need to examine its scheme and authority. +</p> +<p> + To get the scheme for the URI, call {@link android.net.Uri#getScheme() Uri.getScheme()}. The + following code snippet shows you how to determine the scheme and handle the URI accordingly: +</p> +<pre> +public class MainActivity extends Activity { + ... + // A File object containing the path to the transferred files + private File mParentPath; + // Incoming Intent + private Intent mIntent; + ... + /* + * Called from onNewIntent() for a SINGLE_TOP Activity + * or onCreate() for a new Activity. For onNewIntent(), + * remember to call setIntent() to store the most + * current Intent + * + */ + private void handleViewIntent() { + ... + // Get the Intent action + mIntent = getIntent(); + String action = mIntent.getAction(); + /* + * For ACTION_VIEW, the Activity is being asked to display data. + * Get the URI. + */ + if (TextUtils.equals(action, Intent.ACTION_VIEW)) { + // Get the URI from the Intent + Uri beamUri = mIntent.getData(); + /* + * Test for the type of URI, by getting its scheme value + */ + if (TextUtils.equals(beamUri.getScheme(), "file")) { + mParentPath = handleFileUri(beamUri); + } else if (TextUtils.equals( + beamUri.getScheme(), "content")) { + mParentPath = handleContentUri(beamUri); + } + } + ... + } + ... +} +</pre> +<h3>Get the directory from a file URI</h3> +<p> + If the incoming {@link android.content.Intent} contains a file URI, the URI contains the + absolute file name of a file, including the full directory path and file name. For Android Beam + file transfer, the directory path points to the location of the other transferred files, if + any. To get the directory path, get the path part of the URI, which contains all of the URI + except the <code>file:</code> prefix. Create a {@link java.io.File} from the path part, then + get the parent path of the {@link java.io.File}: +</p> +<pre> + ... + public String handleFileUri(Uri beamUri) { + // Get the path part of the URI + String fileName = beamUri.getPath(); + // Create a File object for this filename + File copiedFile = new File(fileName); + // Get a string containing the file's parent directory + return copiedFile.getParent(); + } + ... +</pre> + +<h3 id="GetDirectory">Get the directory from a content URI</h3> +<p> + If the incoming {@link android.content.Intent} contains a content URI, the URI may point to a + directory and file name stored in the {@link android.provider.MediaStore} content provider. You + can detect a content URI for {@link android.provider.MediaStore} by testing the URI's + authority value. A content URI for {@link android.provider.MediaStore} may come from + Android Beam file transfer or from another app, but in both cases you can retrieve a directory + and file name for the content URI. +</p> +<p> + You can also receive an incoming {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} + intent containing a content URI for a content provider other than + {@link android.provider.MediaStore}. In this case, the content URI doesn't contain the + {@link android.provider.MediaStore} authority value, and the content URI usually doesn't point + to a directory. +</p> +<p class="note"> + <strong>Note:</strong> For Android Beam file transfer, you receive a content URI in the + {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent if the first incoming file + has a MIME type of "audio/*", "image/*", or "video/*", indicating that the file is media- + related. Android Beam file transfer indexes the media files it transfers by running Media + Scanner on the directory where it stores transferred files. Media Scanner writes its results + to the {@link android.provider.MediaStore} content provider, then it passes a content URI + for the first file back to Android Beam file transfer. This content URI is the one you + receive in the notification {@link android.content.Intent}. To get the directory + of the first file, you retrieve it from {@link android.provider.MediaStore} using the content + URI. +</p> +<h3>Determine the content provider</h3> +<p> + To determine if you can retrieve a file directory from the content URI, determine the + the content provider associated with the URI by calling + {@link android.net.Uri#getAuthority Uri.getAuthority()} to get the URI's authority. The + result has two possible values: +</p> +<dl> + <dt> + {@link android.provider.MediaStore#AUTHORITY MediaStore.AUTHORITY} + </dt> + <dd> + The URI is for a file or files tracked by {@link android.provider.MediaStore}. Retrieve the + full file name from {@link android.provider.MediaStore}, and get directory from the file + name. + </dd> + <dt> + Any other authority value + </dt> + <dd> + A content URI from another content provider. Display the data associated with the content + URI, but don't get the file directory. + </dd> +</dl> +<p> + To get the directory for a {@link android.provider.MediaStore} content URI, + run a query that specifies the incoming content URI for the {@link android.net.Uri} argument and + the column {@link android.provider.MediaStore.MediaColumns#DATA MediaColumns.DATA} for the + projection. The returned {@link android.database.Cursor} contains the full path and name for + the file represented by the URI. This path also contains all the other files that Android Beam + file transfer just copied to the device. +</p> +<p> + The following snippet shows you how to test the authority of the content URI and retrieve the + the path and file name for the transferred file: +</p> +<pre> + ... + public String handleContentUri(Uri beamUri) { + // Position of the filename in the query Cursor + int filenameIndex; + // File object for the filename + File copiedFile; + // The filename stored in MediaStore + String fileName; + // Test the authority of the URI + if (!TextUtils.equals(beamUri.getAuthority(), MediaStore.AUTHORITY)) { + /* + * Handle content URIs for other content providers + */ + // For a MediaStore content URI + } else { + // Get the column that contains the file name + String[] projection = { MediaStore.MediaColumns.DATA }; + Cursor pathCursor = + getContentResolver().query(beamUri, projection, + null, null, null); + // Check for a valid cursor + if (pathCursor != null && + pathCursor.moveToFirst()) { + // Get the column index in the Cursor + filenameIndex = pathCursor.getColumnIndex( + MediaStore.MediaColumns.DATA); + // Get the full file name including path + fileName = pathCursor.getString(filenameIndex); + // Create a File object for the filename + copiedFile = new File(fileName); + // Return the parent directory of the file + return new File(copiedFile.getParent()); + } else { + // The query didn't work; return null + return null; + } + } + } + ... +</pre> +<p> + To learn more about retrieving data from a content provider, see the section + <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery" + >Retrieving Data from the Provider</a>. +</p> diff --git a/docs/html/training/beam-files/send-files.jd b/docs/html/training/beam-files/send-files.jd new file mode 100644 index 000000000000..917b87f11594 --- /dev/null +++ b/docs/html/training/beam-files/send-files.jd @@ -0,0 +1,294 @@ +page.title=Sending Files to Another Device + +trainingnavtop=true +@jd:body + + +<div id="tb-wrapper"> +<div id="tb"> + +<!-- table of contents --> +<h2>This lesson teaches you to</h2> +<ol> + <li><a href="#DeclareFeatures">Declare Features in the Manifest</a> + <li><a href="#TestAndroidBeam">Test for Android Beam File Transfer Support</a></li> + <li> + <a href="#CreateCallback" + >Create a Callback Method That Provides Files</a> + </li> + <li><a href="#ProvideUri">Specify the Files to Send</a> +</ol> + +<h2>You should also read</h2> +<ul> + <li><a href="{@docRoot}guide/topics/data/data-storage.html">Storage Options</a></li> +</ul> + +</div> +</div> +<p> + This lesson shows you how to design your app to send large files to another device using + Android Beam file transfer. To send files, you request permission to use NFC and external + storage, test to ensure your device supports NFC, and provide URIs to Android Beam file + transfer. +</p> +<p> + The Android Beam file transfer feature has the following requirements: +</p> +<ol> + <li> + Android Beam file transfer for large files is only available in Android 4.1 (API level 16) + and higher. + </li> + <li> + Files you want to transfer must reside in external storage. To learn more about using + external storage, read <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal" + >Using the External Storage</a>. + </li> + <li> + Each file you want to transfer must be world-readable. You can set this permission by + calling the method {@link java.io.File#setReadable File.setReadable(true,false)}. + </li> + <li> + You must provide a file URI for the files you want to transfer. Android Beam file transfer + is unable to handle content URIs generated by + {@link android.support.v4.content.FileProvider#getUriForFile FileProvider.getUriForFile}. + </li> +</ol> + +<h2 id="DeclareFeatures">Declare Features in the Manifest</h2> +<p> + First, edit your app manifest to declare the permissions and features your app needs. +</p> +<h3>Request Permissions</h3> +<p> + To allow your app to use Android Beam file transfer to send files from external storage using + NFC, you must request the following permissions in your app manifest: +</p> +<dl> + <dt> + {@link android.Manifest.permission#NFC NFC} + </dt> + <dd> + Allows your app to send data over NFC. To specify this permission, add the following element + as a child of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" + ><manifest></a></code> element: +<pre> + <uses-permission android:name="android.permission.NFC" /> +</pre> + </dd> + <dt> + {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE} + </dt> + <dd> + Allows your app to read from external storage. To specify this permission, add the following + element as a child of the + <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" + ><manifest></a></code> element: +<pre> + <uses-permission + android:name="android.permission.READ_EXTERNAL_STORAGE" /> +</pre> + <p class="note"> + <strong>Note:</strong> As of Android 4.2.2 (API level 17), this permission is not + enforced. Future versions of the platform may require it for apps that want to read from + external storage. To ensure forward compatibility, request the permission now, before it + becomes required. + </p> + </dd> +</dl> +<h3>Specify the NFC feature</h3> +<p> + Specify that your app uses NFC, by adding a + <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html" + ><uses-feature></a></code> element as a child + of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" + ><manifest></a></code> element. Set the <code>android:required</code> attribute to + <code>true</code> to indicate that your app won't function unless NFC is present. +</p> +<p> + The following snippet shows you how to specify the + <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html" + ><uses-feature></a></code> element: +</p> +<pre> +<uses-feature + android:name="android.hardware.nfc" + android:required="true" /></pre> +<p> + Note that if your app only uses NFC as an option, but still functions if NFC isn't present, you + should set <code>android:required</code> to <code>false</code>, and test for NFC in code. +</p> +<h3>Specify Android Beam file transfer</h3> +<p> + Since Android Beam file transfer is only available in Android 4.1 (API level 16) and later, + if your app depends on Android Beam file transfer for a key part of its functionality you must + specify the <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html" + ><uses-sdk></a></code> element with the + <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min" + >android:minSdkVersion</a>="16"</code> attribute. Otherwise, you can set + <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min" + >android:minSdkVersion</a></code> to another value as necessary, and test for the platform + version in code, as described in the following section. +</p> +<h2 id="TestAndroidBeam">Test for Android Beam File Transfer Support</h2> +<p> + To specify in your app manifest that NFC is optional, you use the following element: +</p> +<pre> +<uses-feature android:name="android.hardware.nfc" android:required="false" /></pre> +<p> + If you set the attribute + <code><a href="guide/topics/manifest/uses-feature-element.html#required" + >android:required</a>="false"</code>, you must test for NFC support and Android Beam file + transfer support in code. +</p> +<p> + To test for Android Beam file transfer support in code, start by testing that the device + supports NFC by calling {@link android.content.pm.PackageManager#hasSystemFeature + PackageManager.hasSystemFeature()} with the argument + {@link android.content.pm.PackageManager#FEATURE_NFC FEATURE_NFC}. Next, check that the Android + version supports Android Beam file transfer by testing the value of + {@link android.os.Build.VERSION#SDK_INT}. If Android Beam file transfer is supported, get an + instance of the NFC controller, which allows you to communicate with the NFC hardware. + For example: +</p> +<pre> +public class MainActivity extends Activity { + ... + NfcAdapter mNfcAdapter; + // Flag to indicate that Android Beam is available + boolean mAndroidBeamAvailable = false; + ... + @Override + protected void onCreate(Bundle savedInstanceState) { + ... + // NFC isn't available on the device + if (!PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) { + /* + * Disable NFC features here. + * For example, disable menu items or buttons that activate + * NFC-related features + */ + ... + // Android Beam file transfer isn't supported + } else if (Build.VERSION.SDK_INT < + Build.VERSION_CODES.JELLY_BEAN_MR1) { + // If Android Beam isn't available, don't continue. + mAndroidBeamAvailable = false; + /* + * Disable Android Beam file transfer features here. + */ + ... + // Android Beam file transfer is available, continue + } else { + mNfcAdapter = NfcAdapter.getDefaultAdapter(this); + ... + } + } + ... +}</pre> + +<h2 id="CreateCallback"> + Create a Callback Method that Provides Files +</h2> +<p> + Once you've verified that the device supports Android Beam file transfer, add a callback + method that the system invokes when Android Beam file transfer detects that the user wants + to send files to another NFC-enabled device. In this callback method, return an array of + {@link android.net.Uri} objects. Android Beam file transfer copies the files represented by + these URIs to the receiving device. +</p> +<p> + To add the callback method, implement the + {@link android.nfc.NfcAdapter.CreateBeamUrisCallback} interface and its method + {@link android.nfc.NfcAdapter.CreateBeamUrisCallback#createBeamUris createBeamUris()}. The + following snippet shows you how to do this: +</p> +<pre> +public class MainActivity extends Activity { + ... + // List of URIs to provide to Android Beam + private Uri[] mFileUris = new Uri[10]; + ... + /** + * Callback that Android Beam file transfer calls to get + * files to share + */ + private class FileUriCallback implements + NfcAdapter.CreateBeamUrisCallback { + public FileUriCallback() { + } + /** + * Create content URIs as needed to share with another device + */ + @Override + public Uri[] createBeamUris(NfcEvent event) { + return mFileUris; + } + } + ... +} +</pre> +<p> + Once you've implemented the interface, provide the callback to Android Beam file transfer by + calling {@link android.nfc.NfcAdapter#setBeamPushUrisCallback setBeamPushUrisCallback()}. The + following snippet shows you how to do this: +</p> +<pre> +public class MainActivity extends Activity { + ... + // Instance that returns available files from this app + private FileUriCallback mFileUriCallback; + ... + @Override + protected void onCreate(Bundle savedInstanceState) { + ... + // Android Beam file transfer is available, continue + ... + mNfcAdapter = NfcAdapter.getDefaultAdapter(this); + /* + * Instantiate a new FileUriCallback to handle requests for + * URIs + */ + mFileUriCallback = new FileUriCallback(); + // Set the dynamic callback for URI requests. + mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this); + ... + } + ... +} +</pre> +<p class="note"> + <strong>Note:</strong> You can also provide the array of {@link android.net.Uri} objects + directly to the NFC framework through your app's {@link android.nfc.NfcAdapter} instance. Choose + this approach if you can define the URIs to transfer before the NFC touch event occurs. + To learn more about this approach, see {@link android.nfc.NfcAdapter#setBeamPushUris + NfcAdapter.setBeamPushUris()}. +</p> +<h2 id="ProvideUri">Specify the Files to Send</h2> +<p> + To transfer one or more files to another NFC-enabled device, get a file URI (a URI with a + <code>file</code> scheme) for each file and then add the URI to an array of + {@link android.net.Uri} objects. To transfer a file, you must also have permanent read access + for the file. For example, the following snippet shows you how to get a file URI from a file + name and then add the URI to the array: +</p> +<pre> + /* + * Create a list of URIs, get a File, + * and set its permissions + */ + private Uri[] mFileUris = new Uri[10]; + String transferFile = "transferimage.jpg"; + File extDir = getExternalFilesDir(null); + File requestFile = new File(extDir, transferFile); + requestFile.setReadable(true, false); + // Get a URI for the File and add it to the list of URIs + fileUri = Uri.fromFile(requestFile); + if (fileUri != null) { + mFileUris[0] = fileUri; + } else { + Log.e("My Activity", "No File URI available for file."); + } +</pre> diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 77ac235e8860..27e7004cadba 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -423,7 +423,22 @@ include the action bar on devices running Android 2.1 or higher." </li> </ul> </li> - + <li class="nav-section"> + <div class="nav-section-header"> + <a href="<?cs var:toroot ?>training/beam-files/index.html" + description= + "How to transfer files between devices using the NFC Android Beam feature." + >Sharing Files with NFC</a> + </div> + <ul> + <li> + <a href="<?cs var:toroot ?>training/beam-files/send-files.html" + >Sending Files to Another Device</a> + </li> + <li><a href="<?cs var:toroot ?>training/beam-files/receive-files.html" + >Receiving Files from Another Device</a></li> + </ul> + </li> <li class="nav-section"> <div class="nav-section-header"> <a href="<?cs var:toroot ?>training/basics/network-ops/index.html" @@ -498,7 +513,7 @@ include the action bar on devices running Android 2.1 or higher." "How to design a robust conflict resolution strategy for apps that save data to the cloud." >Resolving Cloud Save Conflicts </a> - </li> + </li> </li> <li class="nav-section"> <div class="nav-section-header"> @@ -1181,7 +1196,6 @@ include the action bar on devices running Android 2.1 or higher." </a> </div> <ul> - <li> <a href="<?cs var:toroot ?>training/articles/security-tips.html" description= diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index ef858eb0c0bf..5b04a9132612 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -78,7 +78,11 @@ public class Path { mLastDirection = null; if (rects != null) rects.setEmpty(); } + // We promised not to change this, so preserve it around the native + // call, which does now reset fill type. + final FillType fillType = getFillType(); native_reset(mNativePath); + setFillType(fillType); } /** diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index 5ceab36674df..98e3386e7f15 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -28,6 +28,7 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Shader; +import android.graphics.Xfermode; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.LayoutDirection; @@ -531,6 +532,14 @@ public class BitmapDrawable extends Drawable { } /** + * @hide Candidate for future API inclusion + */ + public void setXfermode(Xfermode xfermode) { + mBitmapState.mPaint.setXfermode(xfermode); + invalidateSelf(); + } + + /** * A mutable BitmapDrawable still shares its Bitmap with any other Drawable * that comes from the same resource. * diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 8135716d41e5..8a3d940c63e7 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -17,6 +17,7 @@ package android.graphics.drawable; import android.graphics.Insets; +import android.graphics.Xfermode; import android.os.Trace; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -428,6 +429,15 @@ public abstract class Drawable { public abstract void setColorFilter(ColorFilter cf); /** + * @hide Consider for future API inclusion + */ + public void setXfermode(Xfermode mode) { + // Base implementation drops it on the floor for compatibility. Whee! + // TODO: For this to be included in the API proper, all framework drawables need impls. + // For right now only BitmapDrawable has it. + } + + /** * Specify a color and porterduff mode to be the colorfilter for this * drawable. */ diff --git a/graphics/tests/graphicstests/src/android/graphics/PathTest.java b/graphics/tests/graphicstests/src/android/graphics/PathTest.java new file mode 100644 index 000000000000..96200bc099f9 --- /dev/null +++ b/graphics/tests/graphicstests/src/android/graphics/PathTest.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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. + */ + +package android.graphics; + +import android.test.suitebuilder.annotation.SmallTest; +import junit.framework.TestCase; + + +public class PathTest extends TestCase { + + @SmallTest + public void testResetPreservesFillType() throws Exception { + Path path = new Path(); + + final Path.FillType defaultFillType = path.getFillType(); + final Path.FillType fillType = Path.FillType.INVERSE_EVEN_ODD; + assertFalse(fillType.equals(defaultFillType)); // Sanity check for the test itself. + + path.setFillType(fillType); + path.reset(); + assertEquals(path.getFillType(), fillType); + } +} diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java index d18532117acf..07d91ace46a4 100644 --- a/media/java/android/media/MediaFocusControl.java +++ b/media/java/android/media/MediaFocusControl.java @@ -275,6 +275,13 @@ public class MediaFocusControl implements OnFinished { // tell the RCCs about the change for this RCD enableRemoteControlDisplayForClient_syncRcStack( di.mRcDisplay, di.mEnabled); + // when enabling, refresh the information on the display + if (di.mEnabled) { + sendMsg(mEventHandler, MSG_RCDISPLAY_INIT_INFO, SENDMSG_QUEUE, + di.mArtworkExpectedWidth /*arg1*/, + di.mArtworkExpectedHeight/*arg2*/, + di.mRcDisplay /*obj*/, 0/*delay*/); + } } catch (RemoteException e) { Log.e(TAG, "Error en/disabling RCD: ", e); } diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java index c6d629615f89..7865ec8138de 100644 --- a/media/java/android/media/RemoteController.java +++ b/media/java/android/media/RemoteController.java @@ -36,6 +36,8 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; +import java.lang.ref.WeakReference; + /** * The RemoteController class is used to control media playback, display and update media metadata * and playback status, published by applications using the {@link RemoteControlClient} class. @@ -122,7 +124,7 @@ public final class RemoteController } mOnClientUpdateListener = updateListener; mContext = context; - mRcd = new RcDisplay(); + mRcd = new RcDisplay(this); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); if (ActivityManager.isLowRamDeviceStatic()) { @@ -505,34 +507,51 @@ public final class RemoteController //================================================== // Implementation of IRemoteControlDisplay interface - private class RcDisplay extends IRemoteControlDisplay.Stub { + private static class RcDisplay extends IRemoteControlDisplay.Stub { + private final WeakReference<RemoteController> mController; + + RcDisplay(RemoteController rc) { + mController = new WeakReference<RemoteController>(rc); + } public void setCurrentClientId(int genId, PendingIntent clientMediaIntent, boolean clearing) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } boolean isNew = false; synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { - mClientGenerationIdCurrent = genId; + if (rc.mClientGenerationIdCurrent != genId) { + rc.mClientGenerationIdCurrent = genId; isNew = true; } } if (clientMediaIntent != null) { - sendMsg(mEventHandler, MSG_NEW_PENDING_INTENT, SENDMSG_REPLACE, + sendMsg(rc.mEventHandler, MSG_NEW_PENDING_INTENT, SENDMSG_REPLACE, genId /*arg1*/, 0, clientMediaIntent /*obj*/, 0 /*delay*/); } if (isNew || clearing) { - sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE, + sendMsg(rc.mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE, genId /*arg1*/, clearing ? 1 : 0, null /*obj*/, 0 /*delay*/); } } public void setEnabled(boolean enabled) { - sendMsg(mEventHandler, MSG_DISPLAY_ENABLE, SENDMSG_REPLACE, + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } + sendMsg(rc.mEventHandler, MSG_DISPLAY_ENABLE, SENDMSG_REPLACE, enabled ? 1 : 0 /*arg1*/, 0, null /*obj*/, 0 /*delay*/); } public void setPlaybackState(int genId, int state, long stateChangeTimeMs, long currentPosMs, float speed) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } if (DEBUG) { Log.d(TAG, "> new playback state: genId="+genId + " state="+ state @@ -542,65 +561,81 @@ public final class RemoteController } synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { + if (rc.mClientGenerationIdCurrent != genId) { return; } } final PlaybackInfo playbackInfo = new PlaybackInfo(state, stateChangeTimeMs, currentPosMs, speed); - sendMsg(mEventHandler, MSG_NEW_PLAYBACK_INFO, SENDMSG_REPLACE, + sendMsg(rc.mEventHandler, MSG_NEW_PLAYBACK_INFO, SENDMSG_REPLACE, genId /*arg1*/, 0, playbackInfo /*obj*/, 0 /*delay*/); } public void setTransportControlInfo(int genId, int transportControlFlags, int posCapabilities) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { + if (rc.mClientGenerationIdCurrent != genId) { return; } } - sendMsg(mEventHandler, MSG_NEW_TRANSPORT_INFO, SENDMSG_REPLACE, + sendMsg(rc.mEventHandler, MSG_NEW_TRANSPORT_INFO, SENDMSG_REPLACE, genId /*arg1*/, transportControlFlags /*arg2*/, null /*obj*/, 0 /*delay*/); } public void setMetadata(int genId, Bundle metadata) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } if (DEBUG) { Log.e(TAG, "setMetadata("+genId+")"); } if (metadata == null) { return; } synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { + if (rc.mClientGenerationIdCurrent != genId) { return; } } - sendMsg(mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, + sendMsg(rc.mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, genId /*arg1*/, 0 /*arg2*/, metadata /*obj*/, 0 /*delay*/); } public void setArtwork(int genId, Bitmap artwork) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } if (DEBUG) { Log.v(TAG, "setArtwork("+genId+")"); } synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { + if (rc.mClientGenerationIdCurrent != genId) { return; } } Bundle metadata = new Bundle(1); metadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK), artwork); - sendMsg(mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, + sendMsg(rc.mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, genId /*arg1*/, 0 /*arg2*/, metadata /*obj*/, 0 /*delay*/); } public void setAllMetadata(int genId, Bundle metadata, Bitmap artwork) { + final RemoteController rc = mController.get(); + if (rc == null) { + return; + } if (DEBUG) { Log.e(TAG, "setAllMetadata("+genId+")"); } if ((metadata == null) && (artwork == null)) { return; } synchronized(mGenLock) { - if (mClientGenerationIdCurrent != genId) { + if (rc.mClientGenerationIdCurrent != genId) { return; } } @@ -611,7 +646,7 @@ public final class RemoteController metadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK), artwork); } - sendMsg(mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, + sendMsg(rc.mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, genId /*arg1*/, 0 /*arg2*/, metadata /*obj*/, 0 /*delay*/); } @@ -784,8 +819,34 @@ public final class RemoteController } private void onDisplayEnable(boolean enabled) { + final OnClientUpdateListener l; synchronized(mInfoLock) { mEnabled = enabled; + l = this.mOnClientUpdateListener; + } + if (!enabled) { + // when disabling, reset all info sent to the user + final int genId; + synchronized (mGenLock) { + genId = mClientGenerationIdCurrent; + } + // send "stopped" state, happened "now", playback position is 0, speed 0.0f + final PlaybackInfo pi = new PlaybackInfo(RemoteControlClient.PLAYSTATE_STOPPED, + SystemClock.elapsedRealtime() /*stateChangeTimeMs*/, + 0 /*currentPosMs*/, 0.0f /*speed*/); + sendMsg(mEventHandler, MSG_NEW_PLAYBACK_INFO, SENDMSG_REPLACE, + genId /*arg1*/, 0 /*arg2, ignored*/, pi /*obj*/, 0 /*delay*/); + // send "blank" transport control info: no controls are supported + sendMsg(mEventHandler, MSG_NEW_TRANSPORT_INFO, SENDMSG_REPLACE, + genId /*arg1*/, 0 /*arg2, no flags*/, + null /*obj, ignored*/, 0 /*delay*/); + // send dummy metadata with empty string for title and artist, duration of 0 + Bundle metadata = new Bundle(3); + metadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_TITLE), ""); + metadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ARTIST), ""); + metadata.putLong(String.valueOf(MediaMetadataRetriever.METADATA_KEY_DURATION), 0); + sendMsg(mEventHandler, MSG_NEW_METADATA, SENDMSG_QUEUE, + genId /*arg1*/, 0 /*arg2, ignored*/, metadata /*obj*/, 0 /*delay*/); } } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java index 874e0780f968..3f17aa9b4649 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java @@ -18,9 +18,11 @@ package com.android.mediaframeworktest.unit; import android.os.Parcel; import android.test.suitebuilder.annotation.SmallTest; -import android.graphics.ImageFormat; +import android.graphics.Point; import android.graphics.Rect; -import android.hardware.camera2.CameraMetadata; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CaptureResult; +import android.hardware.camera2.Face; import android.hardware.camera2.Rational; import android.hardware.camera2.Size; import android.hardware.camera2.impl.CameraMetadataNative; @@ -30,9 +32,6 @@ import static android.hardware.camera2.impl.CameraMetadataNative.*; import java.lang.reflect.Array; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.IntBuffer; - -import static org.junit.Assert.assertArrayEquals; /** * <pre> @@ -57,6 +56,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { // Tags static final int ANDROID_COLOR_CORRECTION_MODE = ANDROID_COLOR_CORRECTION_START; static final int ANDROID_COLOR_CORRECTION_TRANSFORM = ANDROID_COLOR_CORRECTION_START + 1; + static final int ANDROID_COLOR_CORRECTION_GAINS = ANDROID_COLOR_CORRECTION_START + 2; static final int ANDROID_CONTROL_AE_ANTIBANDING_MODE = ANDROID_CONTROL_START; static final int ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION = ANDROID_CONTROL_START + 1; @@ -131,7 +131,8 @@ public class CameraMetadataTest extends junit.framework.TestCase { @SmallTest public void testGetTypeFromTag() { assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_MODE)); - assertEquals(TYPE_FLOAT, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertEquals(TYPE_RATIONAL, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertEquals(TYPE_FLOAT, CameraMetadataNative.getNativeType(ANDROID_COLOR_CORRECTION_GAINS)); assertEquals(TYPE_BYTE, CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_ANTIBANDING_MODE)); assertEquals(TYPE_INT32, CameraMetadataNative.getNativeType(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION)); @@ -187,30 +188,30 @@ public class CameraMetadataTest extends junit.framework.TestCase { assertEquals(false, mMetadata.isEmpty()); // - // android.colorCorrection.transform (3x3 matrix) + // android.colorCorrection.colorCorrectionGains (float x 4 array) // - final float[] transformMatrix = new float[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - byte[] transformMatrixAsByteArray = new byte[transformMatrix.length * 4]; - ByteBuffer transformMatrixByteBuffer = - ByteBuffer.wrap(transformMatrixAsByteArray).order(ByteOrder.nativeOrder()); - for (float f : transformMatrix) - transformMatrixByteBuffer.putFloat(f); + final float[] colorCorrectionGains = new float[] { 1.0f, 2.0f, 3.0f, 4.0f}; + byte[] colorCorrectionGainsAsByteArray = new byte[colorCorrectionGains.length * 4]; + ByteBuffer colorCorrectionGainsByteBuffer = + ByteBuffer.wrap(colorCorrectionGainsAsByteArray).order(ByteOrder.nativeOrder()); + for (float f : colorCorrectionGains) + colorCorrectionGainsByteBuffer.putFloat(f); // Read - assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); - mMetadata.writeValues(ANDROID_COLOR_CORRECTION_TRANSFORM, transformMatrixAsByteArray); + assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, colorCorrectionGainsAsByteArray); // Write - assertArrayEquals(transformMatrixAsByteArray, - mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); + assertArrayEquals(colorCorrectionGainsAsByteArray, + mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); assertEquals(2, mMetadata.getEntryCount()); assertEquals(false, mMetadata.isEmpty()); // Erase - mMetadata.writeValues(ANDROID_COLOR_CORRECTION_TRANSFORM, null); - assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_TRANSFORM)); + mMetadata.writeValues(ANDROID_COLOR_CORRECTION_GAINS, null); + assertNull(mMetadata.readValues(ANDROID_COLOR_CORRECTION_GAINS)); assertEquals(1, mMetadata.getEntryCount()); } @@ -279,7 +280,7 @@ public class CameraMetadataTest extends junit.framework.TestCase { @SmallTest public void testReadWritePrimitiveArray() { // int32 (n) - checkKeyGetAndSetArray("android.sensor.info.availableSensitivities", int[].class, + checkKeyGetAndSetArray("android.sensor.info.sensitivityRange", int[].class, new int[] { 0xC0FFEE, 0xDEADF00D }); @@ -379,7 +380,9 @@ public class CameraMetadataTest extends junit.framework.TestCase { new AvailableFormat[] { AvailableFormat.RAW_SENSOR, AvailableFormat.YV12, - AvailableFormat.IMPLEMENTATION_DEFINED + AvailableFormat.IMPLEMENTATION_DEFINED, + AvailableFormat.YCbCr_420_888, + AvailableFormat.BLOB }); } @@ -431,12 +434,13 @@ public class CameraMetadataTest extends junit.framework.TestCase { AvailableFormat.RAW_SENSOR, AvailableFormat.YV12, AvailableFormat.IMPLEMENTATION_DEFINED, - AvailableFormat.YCbCr_420_888 + AvailableFormat.YCbCr_420_888, + AvailableFormat.BLOB }); - Key<AeAntibandingMode> availableFormatsKey = - new Key<AeAntibandingMode>("android.scaler.availableFormats", - AeAntibandingMode.class); + Key<AvailableFormat[]> availableFormatsKey = + new Key<AvailableFormat[]>("android.scaler.availableFormats", + AvailableFormat[].class); byte[] availableFormatValues = mMetadata.readValues(CameraMetadataNative .getTag(availableFormatsKey.getName())); @@ -444,7 +448,8 @@ public class CameraMetadataTest extends junit.framework.TestCase { 0x20, 0x32315659, 0x22, - 0x23 + 0x23, + 0x21 }; ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder()); @@ -523,4 +528,115 @@ public class CameraMetadataTest extends junit.framework.TestCase { <T> void compareGeneric(T expected, T actual) { assertEquals(expected, actual); } + + @SmallTest + public void testReadWriteOverride() { + // + // android.scaler.availableFormats (int x n array) + // + int[] availableFormats = new int[] { + 0x20, // RAW_SENSOR + 0x32315659, // YV12 + 0x11, // YCrCb_420_SP + 0x100, // ImageFormat.JPEG + 0x22, // IMPLEMENTATION_DEFINED + 0x23, // YCbCr_420_888 + }; + int[] expectedIntValues = new int[] { + 0x20, // RAW_SENSOR + 0x32315659, // YV12 + 0x11, // YCrCb_420_SP + 0x21, // BLOB + 0x22, // IMPLEMENTATION_DEFINED + 0x23, // YCbCr_420_888 + }; + int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats"); + + // Write + mMetadata.set(CameraCharacteristics.SCALER_AVAILABLE_FORMATS, availableFormats); + + byte[] availableFormatValues = mMetadata.readValues(availableFormatTag); + + ByteBuffer bf = ByteBuffer.wrap(availableFormatValues).order(ByteOrder.nativeOrder()); + + assertEquals(expectedIntValues.length * 4, availableFormatValues.length); + for (int i = 0; i < expectedIntValues.length; ++i) { + assertEquals(expectedIntValues[i], bf.getInt()); + } + // Read + byte[] availableFormatsAsByteArray = new byte[expectedIntValues.length * 4]; + ByteBuffer availableFormatsByteBuffer = + ByteBuffer.wrap(availableFormatsAsByteArray).order(ByteOrder.nativeOrder()); + for (int value : expectedIntValues) { + availableFormatsByteBuffer.putInt(value); + } + mMetadata.writeValues(availableFormatTag, availableFormatsAsByteArray); + + int[] resultFormats = mMetadata.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS); + assertNotNull("result available formats shouldn't be null", resultFormats); + assertArrayEquals(availableFormats, resultFormats); + + // + // android.statistics.faces (Face x n array) + // + int[] expectedFaceIds = new int[] {1, 2, 3, 4, 5}; + byte[] expectedFaceScores = new byte[] {10, 20, 30, 40, 50}; + int numFaces = expectedFaceIds.length; + Rect[] expectedRects = new Rect[numFaces]; + for (int i = 0; i < numFaces; i++) { + expectedRects[i] = new Rect(i*4 + 1, i * 4 + 2, i * 4 + 3, i * 4 + 4); + } + int[] expectedFaceLM = new int[] { + 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, + }; + Point[] expectedFaceLMPoints = new Point[numFaces * 3]; + for (int i = 0; i < numFaces; i++) { + expectedFaceLMPoints[i*3] = new Point(expectedFaceLM[i*6], expectedFaceLM[i*6+1]); + expectedFaceLMPoints[i*3+1] = new Point(expectedFaceLM[i*6+2], expectedFaceLM[i*6+3]); + expectedFaceLMPoints[i*3+2] = new Point(expectedFaceLM[i*6+4], expectedFaceLM[i*6+5]); + } + + /** + * Read - FACE_DETECT_MODE == FULL + */ + mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, + CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL); + mMetadata.set(CaptureResult.STATISTICS_FACE_IDS, expectedFaceIds); + mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores); + mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects); + mMetadata.set(CaptureResult.STATISTICS_FACE_LANDMARKS, expectedFaceLM); + Face[] resultFaces = mMetadata.get(CaptureResult.STATISTICS_FACES); + assertEquals(numFaces, resultFaces.length); + for (int i = 0; i < numFaces; i++) { + assertEquals(expectedFaceIds[i], resultFaces[i].getId()); + assertEquals(expectedFaceScores[i], resultFaces[i].getScore()); + assertEquals(expectedRects[i], resultFaces[i].getBounds()); + assertEquals(expectedFaceLMPoints[i*3], resultFaces[i].getLeftEyePosition()); + assertEquals(expectedFaceLMPoints[i*3+1], resultFaces[i].getRightEyePosition()); + assertEquals(expectedFaceLMPoints[i*3+2], resultFaces[i].getMouthPosition()); + } + + /** + * Read - FACE_DETECT_MODE == SIMPLE + */ + mMetadata.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, + CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE); + mMetadata.set(CaptureResult.STATISTICS_FACE_SCORES, expectedFaceScores); + mMetadata.set(CaptureResult.STATISTICS_FACE_RECTANGLES, expectedRects); + Face[] resultSimpleFaces = mMetadata.get(CaptureResult.STATISTICS_FACES); + assertEquals(numFaces, resultSimpleFaces.length); + for (int i = 0; i < numFaces; i++) { + assertEquals(Face.ID_UNSUPPORTED, resultSimpleFaces[i].getId()); + assertEquals(expectedFaceScores[i], resultSimpleFaces[i].getScore()); + assertEquals(expectedRects[i], resultSimpleFaces[i].getBounds()); + assertNull(resultSimpleFaces[i].getLeftEyePosition()); + assertNull(resultSimpleFaces[i].getRightEyePosition()); + assertNull(resultSimpleFaces[i].getMouthPosition()); + } + + } } diff --git a/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml b/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml index 851061fe9b51..adbb9da4323f 100644 --- a/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml +++ b/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml @@ -64,7 +64,7 @@ android:layout_weight="0.5" android:layout_marginEnd="12dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="middle" android:textAlignment="viewStart" style="@style/TextAppearance.Medium" /> @@ -83,7 +83,7 @@ android:layout_weight="0.25" android:layout_marginEnd="12dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> @@ -95,7 +95,7 @@ android:layout_marginEnd="12dp" android:minWidth="70dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewEnd" style="@style/TextAppearance.Small" /> @@ -107,7 +107,7 @@ android:layout_marginEnd="12dp" android:minWidth="70dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewEnd" style="@style/TextAppearance.Small" /> diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml index bb5dce1306d7..3aef1cd3bca5 100644 --- a/packages/DocumentsUI/res/layout/item_doc_grid.xml +++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml @@ -67,7 +67,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="middle" android:textAlignment="viewStart" style="@style/TextAppearance.Medium" /> @@ -97,7 +97,7 @@ android:layout_height="wrap_content" android:layout_weight="0.5" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> @@ -108,7 +108,7 @@ android:layout_weight="0.5" android:layout_marginStart="8dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml index 9ba46ac454e6..e3a0dddea66c 100644 --- a/packages/DocumentsUI/res/layout/item_doc_list.xml +++ b/packages/DocumentsUI/res/layout/item_doc_list.xml @@ -68,7 +68,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="middle" android:textAlignment="viewStart" style="@style/TextAppearance.Medium" /> @@ -95,7 +95,7 @@ android:layout_width="90dp" android:layout_height="wrap_content" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> @@ -105,7 +105,7 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> @@ -116,7 +116,7 @@ android:layout_weight="1" android:layout_marginStart="8dp" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml index 9b52d85ca45e..f17c261f7339 100644 --- a/packages/DocumentsUI/res/layout/item_root.xml +++ b/packages/DocumentsUI/res/layout/item_root.xml @@ -43,7 +43,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Medium" /> @@ -52,7 +52,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="end" android:textAlignment="viewStart" style="@style/TextAppearance.Small" /> diff --git a/packages/DocumentsUI/res/layout/item_title.xml b/packages/DocumentsUI/res/layout/item_title.xml index 58016f1fe962..6e96fb534997 100644 --- a/packages/DocumentsUI/res/layout/item_title.xml +++ b/packages/DocumentsUI/res/layout/item_title.xml @@ -38,7 +38,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="middle" android:textAlignment="viewStart" style="@style/TextAppearance.Medium" /> diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java index 22dd6e40285f..90be197b87cb 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java @@ -73,7 +73,7 @@ public class CreateDirectoryFragment extends DialogFragment { final DocumentsActivity activity = (DocumentsActivity) getActivity(); final DocumentInfo cwd = activity.getCurrentDirectory(); - new CreateDirectoryTask(displayName).executeOnExecutor( + new CreateDirectoryTask(activity, cwd, displayName).executeOnExecutor( ProviderExecutor.forAuthority(cwd.authority)); } }); @@ -83,25 +83,26 @@ public class CreateDirectoryFragment extends DialogFragment { } private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> { + private final DocumentsActivity mActivity; + private final DocumentInfo mCwd; private final String mDisplayName; - public CreateDirectoryTask(String displayName) { + public CreateDirectoryTask( + DocumentsActivity activity, DocumentInfo cwd, String displayName) { + mActivity = activity; + mCwd = cwd; mDisplayName = displayName; } @Override protected DocumentInfo doInBackground(Void... params) { - final DocumentsActivity activity = (DocumentsActivity) getActivity(); - final ContentResolver resolver = activity.getContentResolver(); - - final DocumentInfo cwd = activity.getCurrentDirectory(); - + final ContentResolver resolver = mActivity.getContentResolver(); ContentProviderClient client = null; try { client = DocumentsApplication.acquireUnstableProviderOrThrow( - resolver, cwd.derivedUri.getAuthority()); + resolver, mCwd.derivedUri.getAuthority()); final Uri childUri = DocumentsContract.createDocument( - client, cwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName); + client, mCwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName); return DocumentInfo.fromUri(resolver, childUri); } catch (Exception e) { Log.w(TAG, "Failed to create directory", e); @@ -113,12 +114,11 @@ public class CreateDirectoryFragment extends DialogFragment { @Override protected void onPostExecute(DocumentInfo result) { - final DocumentsActivity activity = (DocumentsActivity) getActivity(); if (result != null) { // Navigate into newly created child - activity.onDocumentPicked(result); + mActivity.onDocumentPicked(result); } else { - Toast.makeText(activity, R.string.create_error, Toast.LENGTH_SHORT).show(); + Toast.makeText(mActivity, R.string.create_error, Toast.LENGTH_SHORT).show(); } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java index 4d410d53ee96..1f3901c7bd24 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java @@ -295,6 +295,11 @@ public class DirectoryFragment extends Fragment { updateDisplayState(); + // When launched into empty recents, show drawer + if (mType == TYPE_RECENT_OPEN && mAdapter.isEmpty() && !state.stackTouched) { + ((DocumentsActivity) context).setRootsDrawerOpen(true); + } + // Restore any previous instance state final SparseArray<Parcelable> container = state.dirState.remove(mStateKey); if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java index 76607796d60d..d675e8ddbbd3 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java @@ -292,7 +292,7 @@ public class DocumentsActivity extends Activity { @Override protected Void doInBackground(Void... params) { // Restore last stack for calling package - final String packageName = getCallingPackage(); + final String packageName = getCallingPackageMaybeExtra(); final Cursor cursor = getContentResolver() .query(RecentsProvider.buildResume(packageName), null, null, null, null); try { @@ -783,6 +783,11 @@ public class DocumentsActivity extends Activity { return mState.stack.peek(); } + private String getCallingPackageMaybeExtra() { + final String extra = getIntent().getStringExtra(DocumentsContract.EXTRA_PACKAGE_NAME); + return (extra != null) ? extra : getCallingPackage(); + } + public Executor getCurrentExecutor() { final DocumentInfo cwd = getCurrentDirectory(); if (cwd != null && cwd.authority != null) { @@ -921,7 +926,7 @@ public class DocumentsActivity extends Activity { if (requestCode == CODE_FORWARD && resultCode != RESULT_CANCELED) { // Remember that we last picked via external app - final String packageName = getCallingPackage(); + final String packageName = getCallingPackageMaybeExtra(); final ContentValues values = new ContentValues(); values.put(ResumeColumns.EXTERNAL, 1); getContentResolver().insert(RecentsProvider.buildResume(packageName), values); @@ -1002,7 +1007,7 @@ public class DocumentsActivity extends Activity { } // Remember location for next app launch - final String packageName = getCallingPackage(); + final String packageName = getCallingPackageMaybeExtra(); values.clear(); values.put(ResumeColumns.STACK, rawStack); values.put(ResumeColumns.EXTERNAL, 0); diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java index 39541731eda5..05766f5409d4 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java @@ -109,6 +109,11 @@ public class RecentsCreateFragment extends Fragment { public void onLoadFinished( Loader<List<DocumentStack>> loader, List<DocumentStack> data) { mAdapter.swapStacks(data); + + // When launched into empty recents, show drawer + if (mAdapter.isEmpty() && !state.stackTouched) { + ((DocumentsActivity) context).setRootsDrawerOpen(true); + } } @Override diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index bad0a9605a1b..b98e1eedd7e2 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -21,9 +21,11 @@ import static com.android.documentsui.DocumentsActivity.TAG; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; @@ -158,6 +160,9 @@ public class RootsCache { private class UpdateTask extends AsyncTask<Void, Void, Void> { private final String mFilterPackage; + private final Multimap<String, RootInfo> mTaskRoots = ArrayListMultimap.create(); + private final HashSet<String> mTaskStoppedAuthorities = Sets.newHashSet(); + /** * Update all roots. */ @@ -177,54 +182,54 @@ public class RootsCache { protected Void doInBackground(Void... params) { final long start = SystemClock.elapsedRealtime(); - final Multimap<String, RootInfo> roots = ArrayListMultimap.create(); - final HashSet<String> stoppedAuthorities = Sets.newHashSet(); - - roots.put(mRecentsRoot.authority, mRecentsRoot); + mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot); final ContentResolver resolver = mContext.getContentResolver(); final PackageManager pm = mContext.getPackageManager(); - final List<ProviderInfo> providers = pm.queryContentProviders( - null, -1, PackageManager.GET_META_DATA); - for (ProviderInfo info : providers) { - if (info.metaData != null && info.metaData.containsKey( - DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) { - // Ignore stopped packages for now; we might query them - // later during UI interaction. - if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) { - if (LOGD) Log.d(TAG, "Ignoring stopped authority " + info.authority); - stoppedAuthorities.add(info.authority); - continue; - } - - // Try using cached roots if filtering - boolean cacheHit = false; - if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) { - synchronized (mLock) { - if (roots.putAll(info.authority, mRoots.get(info.authority))) { - if (LOGD) Log.d(TAG, "Used cached roots for " + info.authority); - cacheHit = true; - } - } - } - // Cache miss, or loading everything - if (!cacheHit) { - roots.putAll( - info.authority, loadRootsForAuthority(resolver, info.authority)); - } - } + // Pick up provider with action string + final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE); + final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0); + for (ResolveInfo info : providers) { + handleDocumentsProvider(info.providerInfo); } final long delta = SystemClock.elapsedRealtime() - start; - Log.d(TAG, "Update found " + roots.size() + " roots in " + delta + "ms"); + Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms"); synchronized (mLock) { - mStoppedAuthorities = stoppedAuthorities; - mRoots = roots; + mRoots = mTaskRoots; + mStoppedAuthorities = mTaskStoppedAuthorities; } mFirstLoad.countDown(); return null; } + + private void handleDocumentsProvider(ProviderInfo info) { + // Ignore stopped packages for now; we might query them + // later during UI interaction. + if ((info.applicationInfo.flags & ApplicationInfo.FLAG_STOPPED) != 0) { + if (LOGD) Log.d(TAG, "Ignoring stopped authority " + info.authority); + mTaskStoppedAuthorities.add(info.authority); + return; + } + + // Try using cached roots if filtering + boolean cacheHit = false; + if (mFilterPackage != null && !mFilterPackage.equals(info.packageName)) { + synchronized (mLock) { + if (mTaskRoots.putAll(info.authority, mRoots.get(info.authority))) { + if (LOGD) Log.d(TAG, "Used cached roots for " + info.authority); + cacheHit = true; + } + } + } + + // Cache miss, or loading everything + if (!cacheHit) { + mTaskRoots.putAll(info.authority, + loadRootsForAuthority(mContext.getContentResolver(), info.authority)); + } + } } /** diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java index 2fb12bb29233..fdbc3abf6187 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java @@ -142,9 +142,12 @@ public class RootsFragment extends Fragment { final RootInfo root = ((DocumentsActivity) getActivity()).getCurrentRoot(); for (int i = 0; i < mAdapter.getCount(); i++) { final Object item = mAdapter.getItem(i); - if (Objects.equal(item, root)) { - mList.setItemChecked(i, true); - return; + if (item instanceof RootItem) { + final RootInfo testRoot = ((RootItem) item).root; + if (Objects.equal(testRoot, root)) { + mList.setItemChecked(i, true); + return; + } } } } diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml index 7094efc375b6..99a42600cc5a 100644 --- a/packages/ExternalStorageProvider/AndroidManifest.xml +++ b/packages/ExternalStorageProvider/AndroidManifest.xml @@ -11,9 +11,9 @@ android:grantUriPermissions="true" android:exported="true" android:permission="android.permission.MANAGE_DOCUMENTS"> - <meta-data - android:name="android.content.DOCUMENT_PROVIDER" - android:value="true" /> + <intent-filter> + <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> + </intent-filter> </provider> <!-- TODO: find a better place for tests to live --> @@ -24,9 +24,9 @@ android:exported="true" android:permission="android.permission.MANAGE_DOCUMENTS" android:enabled="false"> - <meta-data - android:name="android.content.DOCUMENT_PROVIDER" - android:value="true" /> + <intent-filter> + <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> + </intent-filter> </provider> </application> </manifest> diff --git a/packages/Keyguard/res/drawable-hdpi/progress_bg_holo_light.9.png b/packages/Keyguard/res/drawable-hdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..2d79280c7d55 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/progress_bg_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-hdpi/progress_primary_holo_light.9.png b/packages/Keyguard/res/drawable-hdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..543cb852769b --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/progress_primary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-hdpi/progress_secondary_holo_light.9.png b/packages/Keyguard/res/drawable-hdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..449705852693 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/progress_secondary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_control_disabled_holo.png b/packages/Keyguard/res/drawable-hdpi/scrubber_control_disabled_holo.png Binary files differnew file mode 100644 index 000000000000..ba778995f9ea --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_control_disabled_holo.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_control_focused_holo.png b/packages/Keyguard/res/drawable-hdpi/scrubber_control_focused_holo.png Binary files differnew file mode 100644 index 000000000000..539ee2253558 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_control_focused_holo.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_control_normal_holo.png b/packages/Keyguard/res/drawable-hdpi/scrubber_control_normal_holo.png Binary files differnew file mode 100644 index 000000000000..9a4ea2f481eb --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_control_normal_holo.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_control_pressed_holo.png b/packages/Keyguard/res/drawable-hdpi/scrubber_control_pressed_holo.png Binary files differnew file mode 100644 index 000000000000..e6b11ded6d66 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_control_pressed_holo.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_primary_holo.9.png b/packages/Keyguard/res/drawable-hdpi/scrubber_primary_holo.9.png Binary files differnew file mode 100644 index 000000000000..822e8d113d0e --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_primary_holo.9.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_secondary_holo.9.png b/packages/Keyguard/res/drawable-hdpi/scrubber_secondary_holo.9.png Binary files differnew file mode 100644 index 000000000000..be4253ec0497 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_secondary_holo.9.png diff --git a/packages/Keyguard/res/drawable-hdpi/scrubber_track_holo_light.9.png b/packages/Keyguard/res/drawable-hdpi/scrubber_track_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..2334e143c1d8 --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/scrubber_track_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/progress_bg_holo_light.9.png b/packages/Keyguard/res/drawable-mdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..ff404337beb1 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/progress_bg_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/progress_primary_holo_light.9.png b/packages/Keyguard/res/drawable-mdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..d5f874df2860 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/progress_primary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/progress_secondary_holo_light.9.png b/packages/Keyguard/res/drawable-mdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..f027007e0e54 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/progress_secondary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_control_disabled_holo.png b/packages/Keyguard/res/drawable-mdpi/scrubber_control_disabled_holo.png Binary files differnew file mode 100644 index 000000000000..981facd14221 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_control_disabled_holo.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_control_focused_holo.png b/packages/Keyguard/res/drawable-mdpi/scrubber_control_focused_holo.png Binary files differnew file mode 100644 index 000000000000..d432f42c952b --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_control_focused_holo.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_control_normal_holo.png b/packages/Keyguard/res/drawable-mdpi/scrubber_control_normal_holo.png Binary files differnew file mode 100644 index 000000000000..7bb749ed8f9b --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_control_normal_holo.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_control_pressed_holo.png b/packages/Keyguard/res/drawable-mdpi/scrubber_control_pressed_holo.png Binary files differnew file mode 100644 index 000000000000..43d826e7f111 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_control_pressed_holo.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_primary_holo.9.png b/packages/Keyguard/res/drawable-mdpi/scrubber_primary_holo.9.png Binary files differnew file mode 100644 index 000000000000..98ac4287f697 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_primary_holo.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_secondary_holo.9.png b/packages/Keyguard/res/drawable-mdpi/scrubber_secondary_holo.9.png Binary files differnew file mode 100644 index 000000000000..d8b563bc9c26 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_secondary_holo.9.png diff --git a/packages/Keyguard/res/drawable-mdpi/scrubber_track_holo_light.9.png b/packages/Keyguard/res/drawable-mdpi/scrubber_track_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..47c5dd95117a --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/scrubber_track_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/progress_bg_holo_light.9.png b/packages/Keyguard/res/drawable-xhdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..dff09393606a --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/progress_bg_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/progress_primary_holo_light.9.png b/packages/Keyguard/res/drawable-xhdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..60b81984cf88 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/progress_primary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/progress_secondary_holo_light.9.png b/packages/Keyguard/res/drawable-xhdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..11b31be3083d --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/progress_secondary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_control_disabled_holo.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_disabled_holo.png Binary files differnew file mode 100644 index 000000000000..ffe913d0c287 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_disabled_holo.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_control_focused_holo.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_focused_holo.png Binary files differnew file mode 100644 index 000000000000..2fccb8f0c5f9 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_focused_holo.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_control_normal_holo.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_normal_holo.png Binary files differnew file mode 100644 index 000000000000..a63850143408 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_normal_holo.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_control_pressed_holo.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_pressed_holo.png Binary files differnew file mode 100644 index 000000000000..f0e65ea1e968 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_control_pressed_holo.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_primary_holo.9.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_primary_holo.9.png Binary files differnew file mode 100644 index 000000000000..04f6ae326a60 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_primary_holo.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_secondary_holo.9.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_secondary_holo.9.png Binary files differnew file mode 100644 index 000000000000..7fef98dd7911 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_secondary_holo.9.png diff --git a/packages/Keyguard/res/drawable-xhdpi/scrubber_track_holo_light.9.png b/packages/Keyguard/res/drawable-xhdpi/scrubber_track_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..a7121697a3e9 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/scrubber_track_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/kg_add_widget_pressed.png b/packages/Keyguard/res/drawable-xxhdpi/kg_add_widget_pressed.png Binary files differnew file mode 100644 index 000000000000..0c0838b0773a --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/kg_add_widget_pressed.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/progress_bg_holo_light.9.png b/packages/Keyguard/res/drawable-xxhdpi/progress_bg_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..60a8e22f892a --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/progress_bg_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/progress_primary_holo_light.9.png b/packages/Keyguard/res/drawable-xxhdpi/progress_primary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..18384d39f326 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/progress_primary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/progress_secondary_holo_light.9.png b/packages/Keyguard/res/drawable-xxhdpi/progress_secondary_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..82eb6155c178 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/progress_secondary_holo_light.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_disabled_holo.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_disabled_holo.png Binary files differnew file mode 100644 index 000000000000..d1ac7ae17be6 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_disabled_holo.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_focused_holo.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_focused_holo.png Binary files differnew file mode 100644 index 000000000000..58a2976f51fe --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_focused_holo.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_normal_holo.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_normal_holo.png Binary files differnew file mode 100644 index 000000000000..6f696fd80e94 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_normal_holo.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_pressed_holo.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_pressed_holo.png Binary files differnew file mode 100644 index 000000000000..faae4e37340e --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_control_pressed_holo.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_primary_holo.9.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_primary_holo.9.png Binary files differnew file mode 100644 index 000000000000..82c2b7eeb889 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_primary_holo.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_secondary_holo.9.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_secondary_holo.9.png Binary files differnew file mode 100644 index 000000000000..800d95e54d27 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_secondary_holo.9.png diff --git a/packages/Keyguard/res/drawable-xxhdpi/scrubber_track_holo_light.9.png b/packages/Keyguard/res/drawable-xxhdpi/scrubber_track_holo_light.9.png Binary files differnew file mode 100644 index 000000000000..9991f7fc0834 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/scrubber_track_holo_light.9.png diff --git a/packages/Keyguard/res/drawable/scrubber_control_selector_holo.xml b/packages/Keyguard/res/drawable/scrubber_control_selector_holo.xml new file mode 100644 index 000000000000..d09b1a516664 --- /dev/null +++ b/packages/Keyguard/res/drawable/scrubber_control_selector_holo.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:drawable="@drawable/scrubber_control_disabled_holo" /> + <item android:state_pressed="true" android:drawable="@drawable/scrubber_control_pressed_holo" /> + <item android:state_selected="true" android:drawable="@drawable/scrubber_control_focused_holo" /> + <item android:drawable="@drawable/scrubber_control_normal_holo" /> +</selector> diff --git a/packages/Keyguard/res/drawable/scrubber_progress_horizontal_holo_light.xml b/packages/Keyguard/res/drawable/scrubber_progress_horizontal_holo_light.xml new file mode 100644 index 000000000000..f07c7420054c --- /dev/null +++ b/packages/Keyguard/res/drawable/scrubber_progress_horizontal_holo_light.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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. +--> + +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/background" + android:drawable="@drawable/scrubber_track_holo_light" /> + <item android:id="@android:id/secondaryProgress"> + <scale android:scaleWidth="100%" + android:drawable="@drawable/scrubber_secondary_holo" /> + </item> + <item android:id="@android:id/progress"> + <scale android:scaleWidth="100%" + android:drawable="@drawable/scrubber_primary_holo" /> + </item> +</layer-list> diff --git a/packages/Keyguard/res/layout/keyguard_status_area.xml b/packages/Keyguard/res/layout/keyguard_status_area.xml index d1f387375668..98ba51241be8 100644 --- a/packages/Keyguard/res/layout/keyguard_status_area.xml +++ b/packages/Keyguard/res/layout/keyguard_status_area.xml @@ -29,8 +29,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/clock_white" - android:format12Hour="@string/abbrev_wday_month_day_no_year" - android:format24Hour="@string/abbrev_wday_month_day_no_year" style="@style/widget_label" android:gravity="center" /> diff --git a/packages/Keyguard/res/layout/keyguard_transport_control_view.xml b/packages/Keyguard/res/layout/keyguard_transport_control_view.xml index 81c742504948..a0b59a7dfb0c 100644 --- a/packages/Keyguard/res/layout/keyguard_transport_control_view.xml +++ b/packages/Keyguard/res/layout/keyguard_transport_control_view.xml @@ -75,7 +75,8 @@ <SeekBar android:id="@+id/transient_seek_bar" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + style="@style/Widget.TransportControl.SeekBar" /> <TextView android:id="@+id/transient_seek_time_elapsed" android:layout_width="wrap_content" diff --git a/packages/Keyguard/res/values-mcc262-mnc07/bools.xml b/packages/Keyguard/res/values-mcc262-mnc07/bools.xml new file mode 100644 index 000000000000..6cd4c55ca940 --- /dev/null +++ b/packages/Keyguard/res/values-mcc262-mnc07/bools.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + <!-- Carriers in this locale are sensitive to capitalization of carrier text. + This makes the entire interface consistent by switching back to normal case. --> + <bool name="kg_use_all_caps">false</bool> +</resources> diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml index 3c004ce03905..01bf6878a2ab 100644 --- a/packages/Keyguard/res/values-uk/strings.xml +++ b/packages/Keyguard/res/values-uk/strings.xml @@ -73,7 +73,7 @@ <string name="keyguard_accessibility_transport_stop_description" msgid="7656358482980912216">"Кнопка \"Зупинити\""</string> <string name="keyguard_accessibility_transport_thumbs_up_description" msgid="4535938129663903194">"Подобається"</string> <string name="keyguard_accessibility_transport_thumbs_down_description" msgid="8101433677192177861">"Не подобається"</string> - <string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Серце"</string> + <string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Рейтинг"</string> <string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"Розблокуйте, щоб продовжити"</string> <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Запуск скасовано"</string> <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"Відпустіть <xliff:g id="WIDGET_INDEX">%1$s</xliff:g>, щоб видалити."</string> diff --git a/packages/Keyguard/res/values/donottranslate.xml b/packages/Keyguard/res/values/donottranslate.xml index 71d3ed7d5ff9..5ee226b78115 100644 --- a/packages/Keyguard/res/values/donottranslate.xml +++ b/packages/Keyguard/res/values/donottranslate.xml @@ -16,7 +16,5 @@ <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- String matching the lock screen format for displaying the date. --> - <string name="abbrev_wday_month_day_no_year">EEE, MMMM d</string> - <!-- Format for describing the date, for accessibility. --> - <string name="full_wday_month_day_no_year">EEEE, MMMM d</string> + <string name="abbrev_wday_month_day_no_year">EEEMMMMd</string> </resources> diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml index 44f560fe2c87..9fd8f31b2d3b 100644 --- a/packages/Keyguard/res/values/styles.xml +++ b/packages/Keyguard/res/values/styles.xml @@ -68,4 +68,18 @@ <item name="android:textSize">@dimen/widget_big_font_size</item> </style> + <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.Holo.SeekBar"> + <item name="android:indeterminateOnly">false</item> + <item name="android:progressDrawable">@drawable/scrubber_progress_horizontal_holo_light</item> + <item name="android:indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_light</item> + <item name="android:minHeight">13dip</item> + <item name="android:maxHeight">13dip</item> + <item name="android:thumb">@drawable/scrubber_control_selector_holo</item> + <item name="android:thumbOffset">16dip</item> + <item name="android:focusable">true</item> + <item name="android:paddingStart">16dip</item> + <item name="android:paddingEnd">16dip</item> + <item name="android:mirrorForRtl">true</item> + </style> + </resources> diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java index 146c0922434c..7d1f24f4963e 100644 --- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java +++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java @@ -19,11 +19,13 @@ package com.android.keyguard; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; import android.os.SystemClock; import android.util.Log; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -55,15 +57,17 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private final WindowManager mWindowManager; private final Point mRenderedSize = new Point(); private final int[] mTmpLoc = new int[2]; - private final Rect mTmpRect = new Rect(); private long mLaunchCameraStart; private boolean mActive; private boolean mTransitioning; private boolean mDown; + private final Rect mInsets = new Rect(); + private FixedSizeFrameLayout mPreview; private View mFullscreenPreview; + private View mFakeNavBar; private final Runnable mTransitionToCameraRunnable = new Runnable() { @Override @@ -211,10 +215,11 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private void render() { final View root = getRootView(); - final int width = root.getWidth(); - final int height = root.getHeight(); + final int width = root.getWidth() - mInsets.right; // leave room + final int height = root.getHeight() - mInsets.bottom; // for bars if (mRenderedSize.x == width && mRenderedSize.y == height) { - if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height)); + if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s %d%%", + width, height, (int)(100*mPreview.getScaleX()))); return; } if (width == 0 || height == 0) { @@ -246,8 +251,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli mPreview.setTranslationY(pvTransY); mRenderedSize.set(width, height); - if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s", - width, height, instanceId())); + if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s %d%% instance=%s", + width, height, (int)(100*mPreview.getScaleX()), instanceId())); } private void transitionToCamera() { @@ -257,24 +262,34 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli enableWindowExitAnimation(false); + final int navHeight = mInsets.bottom; + final int navWidth = mInsets.right; + mPreview.getLocationInWindow(mTmpLoc); final float pvHeight = mPreview.getHeight() * mPreview.getScaleY(); final float pvCenter = mTmpLoc[1] + pvHeight / 2f; final ViewGroup root = (ViewGroup) getRootView(); + + if (DEBUG) { + Log.d(TAG, "root = " + root.getLeft() + "," + root.getTop() + " " + + root.getWidth() + "x" + root.getHeight()); + } + if (mFullscreenPreview == null) { mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo); mFullscreenPreview.setClickable(false); - root.addView(mFullscreenPreview); + root.addView(mFullscreenPreview, new FrameLayout.LayoutParams( + root.getWidth() - navWidth, + root.getHeight() - navHeight)); } - root.getWindowVisibleDisplayFrame(mTmpRect); - final float fsHeight = mTmpRect.height(); - final float fsCenter = mTmpRect.top + fsHeight / 2; + final float fsHeight = root.getHeight() - navHeight; + final float fsCenter = root.getTop() + fsHeight / 2; - final float fsScaleY = pvHeight / fsHeight; + final float fsScaleY = mPreview.getScaleY(); final float fsTransY = pvCenter - fsCenter; - final float fsScaleX = mPreview.getScaleX(); + final float fsScaleX = fsScaleY; mPreview.setVisibility(View.GONE); mFullscreenPreview.setVisibility(View.VISIBLE); @@ -290,6 +305,36 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli .setDuration(WIDGET_ANIMATION_DURATION) .withEndAction(mPostTransitionToCameraEndAction) .start(); + + if (navHeight > 0 || navWidth > 0) { + final boolean atBottom = navHeight > 0; + if (mFakeNavBar == null) { + mFakeNavBar = new View(mContext); + mFakeNavBar.setBackgroundColor(Color.BLACK); + root.addView(mFakeNavBar, new FrameLayout.LayoutParams( + atBottom ? FrameLayout.LayoutParams.MATCH_PARENT + : navWidth, + atBottom ? navHeight + : FrameLayout.LayoutParams.MATCH_PARENT, + atBottom ? Gravity.BOTTOM|Gravity.FILL_HORIZONTAL + : Gravity.RIGHT|Gravity.FILL_VERTICAL)); + mFakeNavBar.setPivotY(navHeight); + mFakeNavBar.setPivotX(navWidth); + } + mFakeNavBar.setAlpha(0f); + if (atBottom) { + mFakeNavBar.setScaleY(0.5f); + } else { + mFakeNavBar.setScaleX(0.5f); + } + mFakeNavBar.setVisibility(View.VISIBLE); + mFakeNavBar.animate() + .alpha(1f) + .scaleY(1f) + .scaleY(1f) + .setDuration(WIDGET_ANIMATION_DURATION) + .start(); + } mCallbacks.onLaunchingCamera(); } @@ -397,6 +442,10 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli mFullscreenPreview.animate().cancel(); mFullscreenPreview.setVisibility(View.GONE); } + if (mFakeNavBar != null) { + mFakeNavBar.animate().cancel(); + mFakeNavBar.setVisibility(View.GONE); + } enableWindowExitAnimation(true); } @@ -404,6 +453,10 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s", w, h, oldw, oldh, SystemClock.uptimeMillis())); + if ((w != oldw && oldw > 0) || (h != oldh && oldh > 0)) { + // we can't trust the old geometry anymore; force a re-render + mRenderedSize.x = mRenderedSize.y = -1; + } mHandler.post(mRenderRunnable); super.onSizeChanged(w, h, oldw, oldh); } @@ -454,4 +507,9 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private String instanceId() { return Integer.toHexString(hashCode()); } + + public void setInsets(Rect insets) { + if (DEBUG) Log.d(TAG, "setInsets: " + insets); + mInsets.set(insets); + } } diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java index 03b09b131524..c33f17477b46 100644 --- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java +++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java @@ -47,6 +47,14 @@ public class CarrierText extends TextView { mSimState = simState; updateCarrierText(mSimState, mPlmn, mSpn); } + + public void onScreenTurnedOff(int why) { + setSelected(false); + }; + + public void onScreenTurnedOn() { + setSelected(true); + }; }; /** * The status of this lock screen. Primarily used for widgets on LockScreen. @@ -79,7 +87,8 @@ public class CarrierText extends TextView { protected void onFinishInflate() { super.onFinishInflate(); mSeparator = getResources().getString(R.string.kg_text_message_separator); - setSelected(true); // Allow marquee to work. + final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); + setSelected(screenOn); // Allow marquee to work. } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java index 63aab4d0d029..ef3d712a30bb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java @@ -405,6 +405,12 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetContainer.setAddWidgetEnabled(false); } checkAppWidgetConsistency(); + + // Don't let the user drag the challenge down if widgets are disabled. + if (mSlidingChallengeLayout != null) { + mSlidingChallengeLayout.setEnableChallengeDragging(!widgetsDisabled()); + } + mSwitchPageRunnable.run(); // This needs to be called after the pages are all added. mViewStateManager.showUsabilityHints(); @@ -972,6 +978,11 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetContainer.setVisibility( isSimOrAccount && fullScreenEnabled ? View.GONE : View.VISIBLE); + // Don't show camera or search in navbar when SIM or Account screen is showing + setSystemUiVisibility(isSimOrAccount ? + (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH) + : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH)); + if (mSlidingChallengeLayout != null) { mSlidingChallengeLayout.setChallengeInteractive(!fullScreenEnabled); } @@ -1443,6 +1454,9 @@ public class KeyguardHostView extends KeyguardViewBase { mInsets.set(insets); if (mSlidingChallengeLayout != null) mSlidingChallengeLayout.setInsets(mInsets); if (mMultiPaneChallengeLayout != null) mMultiPaneChallengeLayout.setInsets(mInsets); + + final CameraWidgetFrame cameraWidget = findCameraPage(); + if (cameraWidget != null) cameraWidget.setInsets(mInsets); } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java index ad59c0267ce7..69075ec3d03a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java @@ -163,6 +163,12 @@ class KeyguardMessageArea extends TextView { mBatteryIsLow = status.isBatteryLow(); update(); } + public void onScreenTurnedOff(int why) { + setSelected(false); + }; + public void onScreenTurnedOn() { + setSelected(true); + }; }; public KeyguardMessageArea(Context context) { @@ -174,9 +180,6 @@ class KeyguardMessageArea extends TextView { mLockPatternUtils = new LockPatternUtils(context); - // This is required to ensure marquee works - setSelected(true); - // Registering this callback immediately updates the battery state, among other things. mUpdateMonitor = KeyguardUpdateMonitor.getInstance(getContext()); mUpdateMonitor.registerCallback(mInfoCallback); @@ -187,6 +190,12 @@ class KeyguardMessageArea extends TextView { update(); } + @Override + protected void onFinishInflate() { + final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); + setSelected(screenOn); // This is required to ensure marquee works + } + public void securityMessageChanged() { setAlpha(1f); mShowingMessage = true; diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java index ffb619bda4da..57fd82ce901f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java @@ -17,23 +17,20 @@ package com.android.keyguard; import android.content.Context; -import android.content.res.Resources; -import android.graphics.Typeface; import android.text.TextUtils; +import android.text.format.DateFormat; import android.util.AttributeSet; +import android.util.Log; import android.util.Slog; import android.view.View; import android.widget.GridLayout; +import android.widget.TextClock; import android.widget.TextView; import com.android.internal.widget.LockPatternUtils; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.Locale; -import libcore.icu.ICU; - public class KeyguardStatusView extends GridLayout { private static final boolean DEBUG = KeyguardViewMediator.DEBUG; private static final String TAG = "KeyguardStatusView"; @@ -41,6 +38,7 @@ public class KeyguardStatusView extends GridLayout { private LockPatternUtils mLockPatternUtils; private TextView mAlarmStatusView; + private TextClock mDateView; private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { @@ -56,6 +54,16 @@ public class KeyguardStatusView extends GridLayout { refresh(); } }; + + @Override + public void onScreenTurnedOn() { + setEnableMarquee(true); + }; + + @Override + public void onScreenTurnedOff(int why) { + setEnableMarquee(false); + }; }; public KeyguardStatusView(Context context) { @@ -70,27 +78,28 @@ public class KeyguardStatusView extends GridLayout { super(context, attrs, defStyle); } + private void setEnableMarquee(boolean enabled) { + if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee"); + if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); - mAlarmStatusView = (TextView) findViewById(R.id.alarm_status); + mDateView = (TextClock) findViewById(R.id.date_view); mLockPatternUtils = new LockPatternUtils(getContext()); - - // Required to get Marquee to work. - final View marqueeViews[] = { mAlarmStatusView }; - for (int i = 0; i < marqueeViews.length; i++) { - View v = marqueeViews[i]; - if (v == null) { - throw new RuntimeException("Can't find widget at index " + i); - } - v.setSelected(true); - } + final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); + setEnableMarquee(screenOn); refresh(); } protected void refresh() { - refreshAlarmStatus(); // might as well + final String fmt = DateFormat.getBestDateTimePattern(Locale.getDefault(), + mContext.getResources().getString(R.string.abbrev_wday_month_day_no_year)); + mDateView.setFormat24Hour(fmt); + mDateView.setFormat12Hour(fmt); + refreshAlarmStatus(); } void refreshAlarmStatus() { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java index 6d7b743058f4..ca4892dee32f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java @@ -22,6 +22,8 @@ import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.MediaMetadataEditor; @@ -198,6 +200,16 @@ public class KeyguardTransportControlView extends FrameLayout { KeyguardHostView.TransportControlCallback mTransportControlCallback; + private final KeyguardUpdateMonitorCallback mUpdateMonitor + = new KeyguardUpdateMonitorCallback() { + public void onScreenTurnedOff(int why) { + setEnableMarquee(false); + }; + public void onScreenTurnedOn() { + setEnableMarquee(true); + }; + }; + public KeyguardTransportControlView(Context context, AttributeSet attrs) { super(context, attrs); if (DEBUG) Log.v(TAG, "Create TCV " + this); @@ -250,6 +262,12 @@ public class KeyguardTransportControlView extends FrameLayout { mTransportControlCallback = transportControlCallback; } + private void setEnableMarquee(boolean enabled) { + if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee"); + if (mTrackTitle != null) mTrackTitle.setSelected(enabled); + if (mTrackArtistAlbum != null) mTrackTitle.setSelected(enabled); + } + @Override public void onFinishInflate() { super.onFinishInflate(); @@ -257,9 +275,7 @@ public class KeyguardTransportControlView extends FrameLayout { mMetadataContainer = (ViewGroup) findViewById(R.id.metadata_container); mBadge = (ImageView) findViewById(R.id.badge); mTrackTitle = (TextView) findViewById(R.id.title); - mTrackTitle.setSelected(true); // enable marquee mTrackArtistAlbum = (TextView) findViewById(R.id.artist_album); - mTrackArtistAlbum.setSelected(true); mTransientSeek = findViewById(R.id.transient_seek); mTransientSeekBar = (SeekBar) findViewById(R.id.transient_seek_bar); mTransientSeekBar.setOnSeekBarChangeListener(mOnSeekBarChangeListener); @@ -273,6 +289,8 @@ public class KeyguardTransportControlView extends FrameLayout { view.setOnClickListener(mTransportCommandListener); view.setOnLongClickListener(mTransportShowSeekBarListener); } + final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); + setEnableMarquee(screenOn); } @Override @@ -285,6 +303,7 @@ public class KeyguardTransportControlView extends FrameLayout { } if (DEBUG) Log.v(TAG, "Registering TCV " + this); mAudioManager.registerRemoteController(mRemoteController); + KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitor); } @Override @@ -301,6 +320,7 @@ public class KeyguardTransportControlView extends FrameLayout { super.onDetachedFromWindow(); if (DEBUG) Log.v(TAG, "Unregistering TCV " + this); mAudioManager.unregisterRemoteController(mRemoteController); + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor); mUserSeeking = false; } @@ -310,6 +330,7 @@ public class KeyguardTransportControlView extends FrameLayout { final ColorMatrix cm = new ColorMatrix(); cm.setSaturation(0); mBadge.setColorFilter(new ColorMatrixColorFilter(cm)); + mBadge.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SCREEN)); mBadge.setImageAlpha(0xef); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 76deb77656c8..45cd3d4bcd2a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -92,7 +92,8 @@ public class KeyguardUpdateMonitor { protected static final int MSG_SET_PLAYBACK_STATE = 316; protected static final int MSG_USER_INFO_CHANGED = 317; protected static final int MSG_REPORT_EMERGENCY_CALL_ACTION = 318; - + private static final int MSG_SCREEN_TURNED_ON = 319; + private static final int MSG_SCREEN_TURNED_OFF = 320; private static KeyguardUpdateMonitor sInstance; @@ -127,6 +128,8 @@ public class KeyguardUpdateMonitor { private boolean mSwitchingUser; + private boolean mScreenOn; + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -185,6 +188,12 @@ public class KeyguardUpdateMonitor { case MSG_REPORT_EMERGENCY_CALL_ACTION: handleReportEmergencyCallAction(); break; + case MSG_SCREEN_TURNED_OFF: + handleScreenTurnedOff(msg.arg1); + break; + case MSG_SCREEN_TURNED_ON: + handleScreenTurnedOn(); + break; } } }; @@ -411,6 +420,26 @@ public class KeyguardUpdateMonitor { return sInstance; } + protected void handleScreenTurnedOn() { + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onScreenTurnedOn(); + } + } + } + + protected void handleScreenTurnedOff(int arg1) { + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); + if (cb != null) { + cb.onScreenTurnedOff(arg1); + } + } + } + /** * IMPORTANT: Must be called from UI thread. */ @@ -1041,4 +1070,24 @@ public class KeyguardUpdateMonitor { public DisplayClientState getCachedDisplayClientState() { return mDisplayClientState; } + + // TODO: use these callbacks elsewhere in place of the existing notifyScreen*() + // (KeyguardViewMediator, KeyguardHostView) + public void dispatchScreenTurnedOn() { + synchronized (this) { + mScreenOn = true; + } + mHandler.sendEmptyMessage(MSG_SCREEN_TURNED_ON); + } + + public void dispatchScreenTurndOff(int why) { + synchronized(this) { + mScreenOn = false; + } + mHandler.sendMessage(mHandler.obtainMessage(MSG_SCREEN_TURNED_OFF, why, 0)); + } + + public boolean isScreenOn() { + return mScreenOn; + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java index e6dddab148f8..76f963733c98 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java @@ -19,6 +19,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManager; import android.graphics.Bitmap; import android.media.AudioManager; +import android.view.WindowManagerPolicy; import com.android.internal.telephony.IccCardConstants; @@ -137,7 +138,23 @@ class KeyguardUpdateMonitorCallback { */ void onEmergencyCallAction() { } + /** + * Called when the transport background changes. + * @param bitmap + */ public void onSetBackground(Bitmap bitmap) { - // THIS SPACE FOR RENT } + + /** + * Called when the screen turns on + */ + public void onScreenTurnedOn() { } + + /** + * Called when the screen turns off + * @param why {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, + * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or + * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}. + */ + public void onScreenTurnedOff(int why) { } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java index 65841805ee31..58ca0b086ce8 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java @@ -420,6 +420,7 @@ public class KeyguardViewManager { public synchronized void onScreenTurnedOn(final IKeyguardShowCallback callback) { if (DEBUG) Log.d(TAG, "onScreenTurnedOn()"); mScreenOn = true; + final IBinder token = mKeyguardHost == null ? null : mKeyguardHost.getWindowToken(); if (mKeyguardView != null) { mKeyguardView.onScreenTurnedOn(); @@ -432,10 +433,6 @@ public class KeyguardViewManager { mKeyguardHost.post(new Runnable() { @Override public void run() { - IBinder token = null; - if (mKeyguardHost.getVisibility() == View.VISIBLE) { - token = mKeyguardHost.getWindowToken(); - } try { callback.onShown(token); } catch (RemoteException e) { @@ -445,7 +442,7 @@ public class KeyguardViewManager { }); } else { try { - callback.onShown(null); + callback.onShown(token); } catch (RemoteException e) { Slog.w(TAG, "Exception calling onShown():", e); } @@ -453,7 +450,7 @@ public class KeyguardViewManager { } } else if (callback != null) { try { - callback.onShown(null); + callback.onShown(token); } catch (RemoteException e) { Slog.w(TAG, "Exception calling onShown():", e); } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index dc28bd09a84e..a37a3a440a7f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -599,6 +599,7 @@ public class KeyguardViewMediator { doKeyguardLocked(null); } } + KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why); } private void doKeyguardLaterLocked() { @@ -664,6 +665,7 @@ public class KeyguardViewMediator { notifyScreenOnLocked(callback); } } + KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOn(); maybeSendUserPresentBroadcast(); } diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java index 4f377a376c75..5e7816c9881e 100644 --- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java +++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java @@ -48,7 +48,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout private static final boolean DEBUG = false; // The drag handle is measured in dp above & below the top edge of the - // challenge view; these parameters change based on whether the challenge + // challenge view; these parameters change based on whether the challenge // is open or closed. private static final int DRAG_HANDLE_CLOSED_ABOVE = 8; // dp private static final int DRAG_HANDLE_CLOSED_BELOW = 0; // dp @@ -81,6 +81,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout private int mScrollState; private OnChallengeScrolledListener mScrollListener; private OnBouncerStateChangedListener mBouncerListener; + private boolean mEnableChallengeDragging; public static final int SCROLL_STATE_IDLE = 0; public static final int SCROLL_STATE_DRAGGING = 1; @@ -263,6 +264,10 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } + public void setEnableChallengeDragging(boolean enabled) { + mEnableChallengeDragging = enabled; + } + public void setInsets(Rect insets) { mInsets.set(insets); } @@ -573,7 +578,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout final float y = ev.getY(i); if (!mIsBouncing && mActivePointerId == INVALID_POINTER && (crossedDragHandle(x, y, mGestureStartY) - || (isInChallengeView(x, y) && + && shouldEnableChallengeDragging() + || (isInChallengeView(x, y) && mScrollState == SCROLL_STATE_SETTLING))) { mActivePointerId = ev.getPointerId(i); mGestureStartX = x; @@ -581,7 +587,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout mGestureStartChallengeBottom = getChallengeBottom(); mDragging = true; enableHardwareLayerForChallengeView(); - } else if (mChallengeShowing && isInChallengeView(x, y)) { + } else if (mChallengeShowing && isInChallengeView(x, y) + && shouldEnableChallengeDragging()) { mBlockDrag = true; } } @@ -596,6 +603,10 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout return mDragging; } + private boolean shouldEnableChallengeDragging() { + return mEnableChallengeDragging || !mChallengeShowing; + } + private boolean isChallengeInteractionBlocked() { return !mChallengeInteractiveExternal || !mChallengeInteractiveInternal; } diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml index 98b5cfe164fa..d503216b26b5 100644 --- a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml +++ b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml @@ -15,9 +15,12 @@ --> <com.android.printspooler.PrintDialogFrame xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/content_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:background="@color/container_background"> + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + <FrameLayout + android:id="@+id/content_container" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:background="@color/container_background"> + </FrameLayout> </com.android.printspooler.PrintDialogFrame> diff --git a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml index 6439b49acc9d..2749aa668ddb 100644 --- a/packages/PrintSpooler/res/layout/printer_dropdown_item.xml +++ b/packages/PrintSpooler/res/layout/printer_dropdown_item.xml @@ -37,7 +37,8 @@ <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="vertical"> + android:orientation="vertical" + android:duplicateParentState="true"> <TextView android:id="@+id/title" diff --git a/packages/PrintSpooler/res/values-be/arrays.xml b/packages/PrintSpooler/res/values-be/arrays.xml new file mode 100644 index 000000000000..d40278c3973d --- /dev/null +++ b/packages/PrintSpooler/res/values-be/arrays.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + + <string-array name="pdf_printer_media_sizes" translatable="false"> + <item>NA_LETTER</item> + <item>NA_GOVT_LETTER</item> + <item>NA_LEGAL</item> + <item>NA_JUNIOR_LEGAL</item> + <item>NA_LEDGER</item> + <item>NA_TABLOID</item> + <item>NA_INDEX_3X5</item> + <item>NA_INDEX_4X6</item> + <item>NA_INDEX_5X8</item> + <item>NA_MONARCH</item> + <item>NA_QUARTO</item> + <item>NA_FOOLSCAP</item> + </string-array> + +</resources> diff --git a/packages/PrintSpooler/res/values-ca/arrays.xml b/packages/PrintSpooler/res/values-ca/arrays.xml new file mode 100644 index 000000000000..d40278c3973d --- /dev/null +++ b/packages/PrintSpooler/res/values-ca/arrays.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + + <string-array name="pdf_printer_media_sizes" translatable="false"> + <item>NA_LETTER</item> + <item>NA_GOVT_LETTER</item> + <item>NA_LEGAL</item> + <item>NA_JUNIOR_LEGAL</item> + <item>NA_LEDGER</item> + <item>NA_TABLOID</item> + <item>NA_INDEX_3X5</item> + <item>NA_INDEX_4X6</item> + <item>NA_INDEX_5X8</item> + <item>NA_MONARCH</item> + <item>NA_QUARTO</item> + <item>NA_FOOLSCAP</item> + </string-array> + +</resources> diff --git a/packages/PrintSpooler/res/values-ca/donottranslate.xml b/packages/PrintSpooler/res/values-ca/donottranslate.xml new file mode 100644 index 000000000000..7537aa50d20c --- /dev/null +++ b/packages/PrintSpooler/res/values-ca/donottranslate.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 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> + + <string name="mediasize_default">NA_LETTER</string> + <string name="mediasize_standard">@string/mediasize_standard_north_america</string> + +</resources> diff --git a/packages/PrintSpooler/res/values-es-rUS/arrays.xml b/packages/PrintSpooler/res/values-es-rUS/arrays.xml new file mode 100644 index 000000000000..d40278c3973d --- /dev/null +++ b/packages/PrintSpooler/res/values-es-rUS/arrays.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + + <string-array name="pdf_printer_media_sizes" translatable="false"> + <item>NA_LETTER</item> + <item>NA_GOVT_LETTER</item> + <item>NA_LEGAL</item> + <item>NA_JUNIOR_LEGAL</item> + <item>NA_LEDGER</item> + <item>NA_TABLOID</item> + <item>NA_INDEX_3X5</item> + <item>NA_INDEX_4X6</item> + <item>NA_INDEX_5X8</item> + <item>NA_MONARCH</item> + <item>NA_QUARTO</item> + <item>NA_FOOLSCAP</item> + </string-array> + +</resources> diff --git a/packages/PrintSpooler/res/values-ja/arrays.xml b/packages/PrintSpooler/res/values-ja/arrays.xml new file mode 100644 index 000000000000..3187cbefaa1e --- /dev/null +++ b/packages/PrintSpooler/res/values-ja/arrays.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + + <string-array name="pdf_printer_media_sizes" translatable="false"> + <item>JIS_B10</item> + <item>JIS_B9</item> + <item>JIS_B8</item> + <item>JIS_B7</item> + <item>JIS_B6</item> + <item>JIS_B5</item> + <item>JIS_B4</item> + <item>JIS_B3</item> + <item>JIS_B2</item> + <item>JIS_B1</item> + <item>JIS_B0</item> + <item>JIS_EXEC</item> + <item>JPN_CHOU4</item> + <item>JPN_CHOU3</item> + <item>JPN_CHOU2</item> + <item>JPN_HAGAKI</item> + <item>JPN_OUFUKU</item> + <item>JPN_KAHU</item> + <item>JPN_KAKU2</item> + <item>JPN_YOU4</item> + </string-array> + +</resources> diff --git a/packages/PrintSpooler/res/values-zh-rCN/arrays.xml b/packages/PrintSpooler/res/values-zh-rCN/arrays.xml new file mode 100644 index 000000000000..4fc75dbcbeb2 --- /dev/null +++ b/packages/PrintSpooler/res/values-zh-rCN/arrays.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + + <string-array name="pdf_printer_media_sizes" translatable="false"> + <item>ROC_8K</item> + <item>ROC_16K</item> + <item>PRC_1</item> + <item>PRC_2</item> + <item>PRC_3</item> + <item>PRC_4</item> + <item>PRC_5</item> + <item>PRC_6</item> + <item>PRC_7</item> + <item>PRC_8</item> + <item>PRC_9</item> + <item>PRC_10</item> + <item>PRC_16K</item> + <item>OM_PA_KAI</item> + <item>OM_DAI_PA_KAI</item> + <item>OM_JUURO_KU_KAI</item> + </string-array> + +</resources> diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml index c82a20ee3497..67c455d730f3 100644 --- a/packages/PrintSpooler/res/values/strings.xml +++ b/packages/PrintSpooler/res/values/strings.xml @@ -121,6 +121,12 @@ <!-- Template for the notificaiton label for a blocked print job. [CHAR LIMIT=25] --> <string name="blocked_notification_title_template">Printer blocked <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string> + <!-- Template for the notificaiton label for a composite (multiple items) print jobs notification. [CHAR LIMIT=25] --> + <plurals name="composite_notification_title_template"> + <item quantity="one"><xliff:g id="print_job_name" example="foo.jpg">%1$d</xliff:g> print job</item> + <item quantity="other"><xliff:g id="print_job_name" example="foo.jpg">%1$d</xliff:g> print jobs</item> + </plurals> + <!-- Label for the notification button for cancelling a print job. [CHAR LIMIT=25] --> <string name="cancel">Cancel</string> diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml index bb41527baacc..86f4a3716110 100644 --- a/packages/PrintSpooler/res/values/themes.xml +++ b/packages/PrintSpooler/res/values/themes.xml @@ -22,6 +22,7 @@ <item name="android:windowIsTranslucent">true</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:colorBackgroundCacheHint">@android:color/transparent</item> + <item name="android:windowIsFloating">true</item> </style> <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light"> diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java index 2bd0443dd9e8..4aa86863b4b2 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java +++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java @@ -17,11 +17,14 @@ package com.android.printspooler; import android.app.Notification; +import android.app.Notification.InboxStyle; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.graphics.drawable.BitmapDrawable; +import android.net.Uri; import android.os.AsyncTask; import android.os.PowerManager; import android.os.PowerManager.WakeLock; @@ -35,6 +38,9 @@ import android.print.PrintManager; import android.provider.Settings; import android.util.Log; +import java.util.ArrayList; +import java.util.List; + /** * This class is responsible for updating the print notifications * based on print job state transitions. @@ -60,29 +66,50 @@ public class NotificationController { mContext.getSystemService(Context.NOTIFICATION_SERVICE); } - public void onPrintJobStateChanged(PrintJobInfo printJob) { - if (DEBUG) { - Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: " - + printJob.getId().flattenToString() + " state:" - + PrintJobInfo.stateToString(printJob.getState())); + public void onUpdateNotifications(List<PrintJobInfo> printJobs) { + List<PrintJobInfo> notifyPrintJobs = new ArrayList<PrintJobInfo>(); + + final int printJobCount = printJobs.size(); + for (int i = 0; i < printJobCount; i++) { + PrintJobInfo printJob = printJobs.get(i); + if (shouldNotifyForState(printJob.getState())) { + notifyPrintJobs.add(printJob); + } } - switch (printJob.getState()) { - case PrintJobInfo.STATE_QUEUED: - case PrintJobInfo.STATE_STARTED: { - createPrintingNotification(printJob); - } break; + updateNotification(notifyPrintJobs); + } + + private void updateNotification(List<PrintJobInfo> printJobs) { + if (printJobs.size() <= 0) { + removeNotification(); + } else if (printJobs.size() == 1) { + createSimpleNotification(printJobs.get(0)); + } else { + createStackedNotification(printJobs); + } + } + + private void createSimpleNotification(PrintJobInfo printJob) { + switch (printJob.getState()) { case PrintJobInfo.STATE_FAILED: { createFailedNotification(printJob); } break; - case PrintJobInfo.STATE_COMPLETED: - case PrintJobInfo.STATE_CANCELED: { - removeNotification(printJob.getId()); + case PrintJobInfo.STATE_BLOCKED: { + if (!printJob.isCancelling()) { + createBlockedNotification(printJob); + } else { + createCancellingNotification(printJob); + } } break; - case PrintJobInfo.STATE_BLOCKED: { - createBlockedNotification(printJob); + default: { + if (!printJob.isCancelling()) { + createPrintingNotification(printJob); + } else { + createCancellingNotification(printJob); + } } break; } } @@ -90,24 +117,22 @@ public class NotificationController { private void createPrintingNotification(PrintJobInfo printJob) { Notification.Builder builder = new Notification.Builder(mContext) .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(com.android.internal.R.drawable.ic_print) - .setContentTitle(mContext.getString(R.string.printing_notification_title_template, - printJob.getLabel())) + .setSmallIcon(computeNotificationIcon(printJob)) + .setContentTitle(computeNotificationTitle(printJob)) .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel), createCancelIntent(printJob)) .setContentText(printJob.getPrinterName()) .setWhen(System.currentTimeMillis()) .setOngoing(true) .setShowWhen(true); - mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build()); + mNotificationManager.notify(0, builder.build()); } private void createFailedNotification(PrintJobInfo printJob) { Notification.Builder builder = new Notification.Builder(mContext) .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(com.android.internal.R.drawable.ic_print_error) - .setContentTitle(mContext.getString(R.string.failed_notification_title_template, - printJob.getLabel())) + .setSmallIcon(computeNotificationIcon(printJob)) + .setContentTitle(computeNotificationTitle(printJob)) .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel), createCancelIntent(printJob)) .addAction(R.drawable.ic_restart, mContext.getString(R.string.restart), @@ -116,32 +141,109 @@ public class NotificationController { .setWhen(System.currentTimeMillis()) .setOngoing(true) .setShowWhen(true); - mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build()); + mNotificationManager.notify(0, builder.build()); } private void createBlockedNotification(PrintJobInfo printJob) { Notification.Builder builder = new Notification.Builder(mContext) .setContentIntent(createContentIntent(printJob.getId())) - .setSmallIcon(com.android.internal.R.drawable.ic_print_error) - .setContentTitle(mContext.getString(R.string.blocked_notification_title_template, - printJob.getLabel())) + .setSmallIcon(computeNotificationIcon(printJob)) + .setContentTitle(computeNotificationTitle(printJob)) .addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel), createCancelIntent(printJob)) .setContentText(printJob.getPrinterName()) .setWhen(System.currentTimeMillis()) .setOngoing(true) .setShowWhen(true); - mNotificationManager.notify(printJob.getId().flattenToString(), 0, builder.build()); + mNotificationManager.notify(0, builder.build()); } - private void removeNotification(PrintJobId printJobId) { - mNotificationManager.cancel(printJobId.flattenToString(), 0); + private void createCancellingNotification(PrintJobInfo printJob) { + Notification.Builder builder = new Notification.Builder(mContext) + .setContentIntent(createContentIntent(printJob.getId())) + .setSmallIcon(computeNotificationIcon(printJob)) + .setContentTitle(computeNotificationTitle(printJob)) + .setContentText(printJob.getPrinterName()) + .setWhen(System.currentTimeMillis()) + .setOngoing(true) + .setShowWhen(true); + mNotificationManager.notify(0, builder.build()); + } + + private void createStackedNotification(List<PrintJobInfo> printJobs) { + Notification.Builder builder = new Notification.Builder(mContext) + .setContentIntent(createContentIntent(null)) + .setWhen(System.currentTimeMillis()) + .setOngoing(true) + .setShowWhen(true); + + final int printJobCount = printJobs.size(); + + InboxStyle inboxStyle = new InboxStyle(); + inboxStyle.setBigContentTitle(String.format(mContext.getResources().getQuantityText( + R.plurals.composite_notification_title_template, + printJobCount).toString(), printJobCount)); + + for (int i = printJobCount - 1; i>= 0; i--) { + PrintJobInfo printJob = printJobs.get(i); + if (i == printJobCount - 1) { + builder.setLargeIcon(((BitmapDrawable) mContext.getResources().getDrawable( + computeNotificationIcon(printJob))).getBitmap()); + builder.setSmallIcon(com.android.internal.R.drawable.ic_print); + builder.setContentTitle(computeNotificationTitle(printJob)); + builder.setContentText(printJob.getPrinterName()); + } + inboxStyle.addLine(computeNotificationTitle(printJob)); + } + + builder.setNumber(printJobCount); + builder.setStyle(inboxStyle); + + mNotificationManager.notify(0, builder.build()); + } + + private String computeNotificationTitle(PrintJobInfo printJob) { + switch (printJob.getState()) { + case PrintJobInfo.STATE_FAILED: { + return mContext.getString(R.string.failed_notification_title_template, + printJob.getLabel()); + } + + case PrintJobInfo.STATE_BLOCKED: { + if (!printJob.isCancelling()) { + return mContext.getString(R.string.blocked_notification_title_template, + printJob.getLabel()); + } else { + return mContext.getString( + R.string.cancelling_notification_title_template, + printJob.getLabel()); + } + } + + default: { + if (!printJob.isCancelling()) { + return mContext.getString(R.string.printing_notification_title_template, + printJob.getLabel()); + } else { + return mContext.getString( + R.string.cancelling_notification_title_template, + printJob.getLabel()); + } + } + } + } + + private void removeNotification() { + mNotificationManager.cancel(0); } private PendingIntent createContentIntent(PrintJobId printJobId) { Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS); - intent.putExtra(EXTRA_PRINT_JOB_ID, printJobId.flattenToString()); - return PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); + if (printJobId != null) { + intent.putExtra(EXTRA_PRINT_JOB_ID, printJobId.flattenToString()); + intent.setData(Uri.fromParts("printjob", printJobId.flattenToString(), null)); + } + return PendingIntent.getActivity(mContext, 0, intent, 0); } private PendingIntent createCancelIntent(PrintJobInfo printJob) { @@ -160,6 +262,36 @@ public class NotificationController { return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT); } + private static boolean shouldNotifyForState(int state) { + switch (state) { + case PrintJobInfo.STATE_QUEUED: + case PrintJobInfo.STATE_STARTED: + case PrintJobInfo.STATE_FAILED: + case PrintJobInfo.STATE_COMPLETED: + case PrintJobInfo.STATE_CANCELED: + case PrintJobInfo.STATE_BLOCKED: { + return true; + } + } + return false; + } + + private static int computeNotificationIcon(PrintJobInfo printJob) { + switch (printJob.getState()) { + case PrintJobInfo.STATE_FAILED: + case PrintJobInfo.STATE_BLOCKED: { + return com.android.internal.R.drawable.ic_print_error; + } + default: { + if (!printJob.isCancelling()) { + return com.android.internal.R.drawable.ic_print; + } else { + return R.drawable.stat_notify_cancelling; + } + } + } + } + public static final class NotificationBroadcastReceiver extends BroadcastReceiver { private static final String LOG_TAG = "NotificationBroadcastReceiver"; @@ -183,20 +315,6 @@ public class NotificationController { Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId); } - // Put up a notification that we are trying to cancel. - NotificationManager notificationManager = (NotificationManager) - context.getSystemService(Context.NOTIFICATION_SERVICE); - Notification.Builder builder = new Notification.Builder(context) - .setSmallIcon(R.drawable.stat_notify_cancelling) - .setContentTitle(context.getString( - R.string.cancelling_notification_title_template, - printJobLabel)) - .setContentText(printerName) - .setWhen(System.currentTimeMillis()) - .setOngoing(true) - .setShowWhen(true); - notificationManager.notify(printJobId.flattenToString(), 0, builder.build()); - // Call into the print manager service off the main thread since // the print manager service may end up binding to the print spooler // service which binding is handled on the main thread. @@ -217,8 +335,8 @@ public class NotificationController { // done on another thread and until it finishes the spooler has // to be kept around. try { - IPrintManager printManager = IPrintManager.Stub.asInterface( - ServiceManager.getService(Context.PRINT_SERVICE)); + IPrintManager printManager = IPrintManager.Stub.asInterface( + ServiceManager.getService(Context.PRINT_SERVICE)); printManager.cancelPrintJob(printJobId, PrintManager.APP_ID_ANY, UserHandle.myUserId()); } catch (RemoteException re) { diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java b/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java index 6dd8aa0a6597..c1c4d2156716 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintDialogFrame.java @@ -24,6 +24,8 @@ public class PrintDialogFrame extends FrameLayout { public final int mMaxWidth; + public int mHeight; + public PrintDialogFrame(Context context, AttributeSet attrs) { super(context, attrs); mMaxWidth = context.getResources().getDimensionPixelSize( @@ -32,13 +34,36 @@ public class PrintDialogFrame extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + int measuredWidth = getMeasuredWidth(); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode == MeasureSpec.AT_MOST) { - final int receivedWidth = MeasureSpec.getSize(widthMeasureSpec); - final int computedWidth = Math.min(mMaxWidth, receivedWidth); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(computedWidth, - MeasureSpec.EXACTLY); + switch (widthMode) { + case MeasureSpec.UNSPECIFIED: { + measuredWidth = mMaxWidth; + } break; + + case MeasureSpec.AT_MOST: { + final int receivedWidth = MeasureSpec.getSize(widthMeasureSpec); + measuredWidth = Math.min(mMaxWidth, receivedWidth); + } break; } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + mHeight = Math.max(mHeight, getMeasuredHeight()); + + int measuredHeight = getMeasuredHeight(); + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + switch (heightMode) { + case MeasureSpec.UNSPECIFIED: { + measuredHeight = mHeight; + } break; + + case MeasureSpec.AT_MOST: { + final int receivedHeight = MeasureSpec.getSize(heightMeasureSpec); + measuredHeight = Math.min(mHeight, receivedHeight); + } break; + } + + setMeasuredDimension(measuredWidth, measuredHeight); } } diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java index 7f9be6ce702a..2922dd1e9535 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java @@ -59,12 +59,14 @@ import android.text.TextWatcher; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; +import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.View.MeasureSpec; import android.view.View.OnAttachStateChangeListener; import android.view.View.OnClickListener; +import android.view.ViewGroup.LayoutParams; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; @@ -75,6 +77,7 @@ import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; @@ -456,6 +459,7 @@ public class PrintJobConfigActivity extends Activity { // Then update the print jobs's pages as we will not do a write // and we usually update the pages in the write complete callback. updatePrintJobPages(mDocument.pages, mRequestedPages); + mEditor.updateUi(); if (mEditor.isDone()) { requestCreatePdfFileOrFinish(); } @@ -555,6 +559,7 @@ public class PrintJobConfigActivity extends Activity { // TODO: We need some UI for announcing an error. mControllerState = CONTROLLER_STATE_FAILED; Log.e(LOG_TAG, "Received invalid pages from the app"); + mEditor.cancel(); PrintJobConfigActivity.this.finish(); } } @@ -1152,6 +1157,9 @@ public class PrintJobConfigActivity extends Activity { if (!mFavoritePrinterSelected && mDestinationSpinnerAdapter.getCount() > 2) { mFavoritePrinterSelected = true; mDestinationSpinner.setSelection(0); + // Workaround again the weird spinner behavior to notify for selection + // change on the next layout pass as the current printer is used below. + mCurrentPrinter = (PrinterInfo) mDestinationSpinnerAdapter.getItem(0); } // If there is a next printer to select and we succeed selecting @@ -1404,7 +1412,9 @@ public class PrintJobConfigActivity extends Activity { postSwitchCallback.run(); } } - }); + }, + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); } break; } } break; @@ -1421,7 +1431,9 @@ public class PrintJobConfigActivity extends Activity { postSwitchCallback.run(); } } - }); + }, + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER)); } break; } } break; @@ -1469,7 +1481,8 @@ public class PrintJobConfigActivity extends Activity { getLayoutInflater().inflate(showLayoutId, contentContainer, true); } - private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand) { + private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand, + final LayoutParams containerParams) { // Find everything we will shuffle around. final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container); final View hidingView = contentContainer.getChildAt(0); @@ -1506,6 +1519,8 @@ public class PrintJobConfigActivity extends Activity { contentContainer.setScaleY(1.0f); contentContainer.addView(showingView); + contentContainer.setLayoutParams(containerParams); + // Third animation - show the new content. AutoCancellingAnimator.animate(showingView).withLayer().alpha(1.0f) .withEndAction(new Runnable() { diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java index d1b42bccc5fb..e1ddb4011fab 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java @@ -230,6 +230,11 @@ public final class PrintSpoolerService extends Service { protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { PrintSpoolerService.this.dump(fd, writer, args); } + + @Override + public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { + PrintSpoolerService.this.setPrintJobCancelling(printJobId, cancelling); + } }; } @@ -459,8 +464,6 @@ public final class PrintSpoolerService extends Service { fileForJobMap.remove(printJob.getId()); } - // Update the notification. - mNotificationController.onPrintJobStateChanged(printJob); switch (printJob.getState()) { case PrintJobInfo.STATE_QUEUED: case PrintJobInfo.STATE_STARTED: @@ -475,6 +478,11 @@ public final class PrintSpoolerService extends Service { } } + if (!mPrintJobs.isEmpty()) { + // Update the notification. + mNotificationController.onUpdateNotifications(mPrintJobs); + } + // Delete the orphan files. if (fileForJobMap != null) { final int orphanFileCount = fileForJobMap.size(); @@ -586,7 +594,7 @@ public final class PrintSpoolerService extends Service { printJob.setState(state); printJob.setStateReason(error); - mNotificationController.onPrintJobStateChanged(printJob); + printJob.setCancelling(false); if (DEBUG_PRINT_JOB_LIFECYCLE) { Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob); @@ -626,6 +634,8 @@ public final class PrintSpoolerService extends Service { HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, printJob); mHandlerCaller.executeOrSendMessage(message); + + mNotificationController.onUpdateNotifications(mPrintJobs); } } @@ -694,6 +704,24 @@ public final class PrintSpoolerService extends Service { return false; } + public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { + synchronized (mLock) { + PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); + if (printJob != null) { + printJob.setCancelling(cancelling); + if (shouldPersistPrintJob(printJob)) { + mPersistanceManager.writeStateLocked(); + } + mNotificationController.onUpdateNotifications(mPrintJobs); + + Message message = mHandlerCaller.obtainMessageO( + HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, + printJob); + mHandlerCaller.executeOrSendMessage(message); + } + } + } + public void setPrintJobCopiesNoPersistence(PrintJobId printJobId, int copies) { synchronized (mLock) { PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY); @@ -783,6 +811,7 @@ public final class PrintSpoolerService extends Service { private static final String ATTR_COPIES = "copies"; private static final String ATTR_PRINTER_NAME = "printerName"; private static final String ATTR_STATE_REASON = "stateReason"; + private static final String ATTR_CANCELLING = "cancelling"; private static final String TAG_MEDIA_SIZE = "mediaSize"; private static final String TAG_RESOLUTION = "resolution"; @@ -881,6 +910,8 @@ public final class PrintSpoolerService extends Service { if (!TextUtils.isEmpty(stateReason)) { serializer.attribute(null, ATTR_STATE_REASON, stateReason); } + serializer.attribute(null, ATTR_CANCELLING, String.valueOf( + printJob.isCancelling())); PrinterId printerId = printJob.getPrinterId(); if (printerId != null) { @@ -1073,6 +1104,9 @@ public final class PrintSpoolerService extends Service { printJob.setPrinterName(printerName); String stateReason = parser.getAttributeValue(null, ATTR_STATE_REASON); printJob.setStateReason(stateReason); + String cancelling = parser.getAttributeValue(null, ATTR_CANCELLING); + printJob.setCancelling(!TextUtils.isEmpty(cancelling) + ? Boolean.parseBoolean(cancelling) : false); parser.next(); diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java index b8a9417a2faa..d68893236ca8 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java +++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java @@ -52,6 +52,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Filter; @@ -138,13 +139,19 @@ public final class SelectPrinterFragment extends ListFragment { searchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View view) { - view.announceForAccessibility(getString( - R.string.print_search_box_shown_utterance)); + if (AccessibilityManager.getInstance(getActivity()).isEnabled()) { + view.announceForAccessibility(getString( + R.string.print_search_box_shown_utterance)); + } } @Override public void onViewDetachedFromWindow(View view) { - view.announceForAccessibility(getString( - R.string.print_search_box_hidden_utterance)); + Activity activity = getActivity(); + if (activity != null && !activity.isFinishing() + && AccessibilityManager.getInstance(activity).isEnabled()) { + view.announceForAccessibility(getString( + R.string.print_search_box_hidden_utterance)); + } } }); @@ -161,6 +168,14 @@ public final class SelectPrinterFragment extends ListFragment { } @Override + public void onPause() { + if (mAnnounceFilterResult != null) { + mAnnounceFilterResult.remove(); + } + super.onPause(); + } + + @Override public void onListItemClick(ListView list, View view, int position, long id) { PrinterInfo printer = (PrinterInfo) list.getAdapter().getItem(position); Activity activity = getActivity(); @@ -259,11 +274,13 @@ public final class SelectPrinterFragment extends ListFragment { } } - private void announceSearchResult() { - if (mAnnounceFilterResult == null) { - mAnnounceFilterResult = new AnnounceFilterResult(); + private void announceSearchResultIfNeeded() { + if (AccessibilityManager.getInstance(getActivity()).isEnabled()) { + if (mAnnounceFilterResult == null) { + mAnnounceFilterResult = new AnnounceFilterResult(); + } + mAnnounceFilterResult.post(); } - mAnnounceFilterResult.post(); } public static class AddPrinterAlertDialogFragment extends DialogFragment { @@ -390,7 +407,7 @@ public final class SelectPrinterFragment extends ListFragment { resultCountChanged = (oldPrinterCount != mFilteredPrinters.size()); } if (resultCountChanged) { - announceSearchResult(); + announceSearchResultIfNeeded(); } notifyDataSetChanged(); } @@ -435,6 +452,8 @@ public final class SelectPrinterFragment extends ListFragment { R.layout.printer_dropdown_item, parent, false); } + convertView.setEnabled(isEnabled(position)); + CharSequence title = null; CharSequence subtitle = null; Drawable icon = null; @@ -476,6 +495,12 @@ public final class SelectPrinterFragment extends ListFragment { } @Override + public boolean isEnabled(int position) { + PrinterInfo printer = (PrinterInfo) getItem(position); + return printer.getStatus() != PrinterInfo.STATUS_UNAVAILABLE; + } + + @Override public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) { if (id == LOADER_ID_PRINTERS_LOADER) { return new FusedPrintersProvider(getActivity()); diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index bfb0931c5dae..a1d8f22d48a9 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -168,4 +168,9 @@ <!-- Default for Settings.Secure.USER_SETUP_COMPLETE --> <bool name="def_user_setup_complete">false</bool> + + <!-- Default for Settings.Global.LOW_BATTERY_SOUND_TIMEOUT. + 0 means no timeout; battery sounds will always play + >0 is milliseconds of screen-off time after which battery sounds will not play --> + <integer name="def_low_battery_sound_timeout">0</integer> </resources> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 120b28f2fcbd..09c21f3f1997 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -72,7 +72,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { // 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 = 97; + private static final int DATABASE_VERSION = 98; private Context mContext; private int mUserHandle; @@ -1541,6 +1541,24 @@ public class DatabaseHelper extends SQLiteOpenHelper { upgradeVersion = 97; } + if (upgradeVersion == 97) { + if (mUserHandle == UserHandle.USER_OWNER) { + db.beginTransaction(); + SQLiteStatement stmt = null; + try { + stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)" + + " VALUES(?,?);"); + loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, + R.integer.def_low_battery_sound_timeout); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + if (stmt != null) stmt.close(); + } + } + upgradeVersion = 98; + } + // *** Remember to update DATABASE_VERSION above! if (upgradeVersion != currentVersion) { @@ -2253,6 +2271,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION); loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type); + loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, + R.integer.def_low_battery_sound_timeout); + // --- New global settings start here } finally { if (stmt != null) stmt.close(); diff --git a/packages/SystemUI/res/drawable-hdpi/bottom_divider_glow.png b/packages/SystemUI/res/drawable-hdpi/bottom_divider_glow.png Binary files differindex e8cfc0f61f2a..d1948d605c13 100644 --- a/packages/SystemUI/res/drawable-hdpi/bottom_divider_glow.png +++ b/packages/SystemUI/res/drawable-hdpi/bottom_divider_glow.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png Binary files differdeleted file mode 100644 index beb0e058d188..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png Binary files differdeleted file mode 100644 index 14832c5f5c35..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png Binary files differdeleted file mode 100644 index 603fff1daa7d..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png Binary files differdeleted file mode 100644 index 5556d6a20192..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png Binary files differdeleted file mode 100644 index 0004633ae14b..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png Binary files differdeleted file mode 100644 index abd336bdd8e7..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png Binary files differdeleted file mode 100644 index f23dda803c3d..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png Binary files differdeleted file mode 100644 index c7482a90d977..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png Binary files differdeleted file mode 100644 index 29a853d76662..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_orange.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png Binary files differdeleted file mode 100644 index 988aa129f5dd..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_red.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png Binary files differdeleted file mode 100644 index 64c0d827d0f4..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_bang_white.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png Binary files differdeleted file mode 100644 index 9ab1d8f6f990..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png Binary files differdeleted file mode 100644 index e8f92e21a85c..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png Binary files differdeleted file mode 100644 index 0d01eb56a59a..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png Binary files differdeleted file mode 100644 index 3d66ffbc947a..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png Binary files differdeleted file mode 100644 index 3562cea1ab57..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png Binary files differdeleted file mode 100644 index 2b2ebf6f07d5..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png Binary files differdeleted file mode 100644 index f9f9537b7c9e..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png Binary files differdeleted file mode 100644 index 2c7532a81109..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_charge_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png Binary files differdeleted file mode 100644 index ebcd33695f1b..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_battery_unknown.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png Binary files differdeleted file mode 100644 index f82a0371dd63..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_circle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png Binary files differdeleted file mode 100644 index ed6c0db565d8..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_hour.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png Binary files differdeleted file mode 100644 index e28c06a9a5b3..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_clock_minute.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png Binary files differindex 8b6ecc20b7e3..a53108d0c966 100644 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_settings.png diff --git a/packages/SystemUI/res/drawable-hdpi/nav_background.9.png b/packages/SystemUI/res/drawable-hdpi/nav_background.9.png Binary files differindex db36d2b253aa..a09e654ee7fa 100644 --- a/packages/SystemUI/res/drawable-hdpi/nav_background.9.png +++ b/packages/SystemUI/res/drawable-hdpi/nav_background.9.png diff --git a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png Binary files differdeleted file mode 100644 index 080f2f25a02e..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/recents_thumbnail_bg_dragging.9.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/search_light.png b/packages/SystemUI/res/drawable-hdpi/search_light.png Binary files differindex c64ae19777f8..116b1f0946d5 100644 --- a/packages/SystemUI/res/drawable-hdpi/search_light.png +++ b/packages/SystemUI/res/drawable-hdpi/search_light.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png Binary files differdeleted file mode 100644 index 4ff22d2762ce..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png Binary files differdeleted file mode 100644 index 612b3622176a..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png Binary files differdeleted file mode 100644 index c971443da621..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png Binary files differdeleted file mode 100644 index a6d47967bea1..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png Binary files differdeleted file mode 100644 index 67a6a731ff14..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png Binary files differdeleted file mode 100644 index f972ebd2e8f2..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png Binary files differdeleted file mode 100644 index b707fa1de37c..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png Binary files differdeleted file mode 100644 index 82d654531e97..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png Binary files differdeleted file mode 100644 index fe33891b8e58..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png Binary files differdeleted file mode 100644 index edd03e360814..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png Binary files differdeleted file mode 100644 index 5d90d2b29138..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png Binary files differdeleted file mode 100644 index 9e18046f6f4f..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png Binary files differdeleted file mode 100644 index a2f2cf73ec07..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png Binary files differdeleted file mode 100644 index bd5d92246431..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png Binary files differdeleted file mode 100644 index 9a021998a4bd..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png Binary files differdeleted file mode 100644 index aa1b25c4e9f7..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_charge_anim85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index 432b16600928..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index aa071c777cf1..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 194698a05200..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 0b4b368f3656..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index 8887f2e0f366..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index 87c3244df27f..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 8206cd85a192..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index 293f88cde239..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index cb9c8ac250f6..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index 88eafcbdc0fe..000000000000 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png Binary files differindex 9befc3432aab..d43d1dc7e0e5 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png diff --git a/packages/SystemUI/res/drawable-hdpi/status_background.9.png b/packages/SystemUI/res/drawable-hdpi/status_background.9.png Binary files differindex 66d1467507e7..7957c593d225 100644 --- a/packages/SystemUI/res/drawable-hdpi/status_background.9.png +++ b/packages/SystemUI/res/drawable-hdpi/status_background.9.png diff --git a/packages/SystemUI/res/drawable-hdpi/top_divider_glow.png b/packages/SystemUI/res/drawable-hdpi/top_divider_glow.png Binary files differindex 89cd10ef92cc..a540efb181f4 100644 --- a/packages/SystemUI/res/drawable-hdpi/top_divider_glow.png +++ b/packages/SystemUI/res/drawable-hdpi/top_divider_glow.png diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index 295d8fa7db5a..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index d875fafd702d..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index f3235e4a1a70..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 6cd48091de70..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index 9bbf17ec0544..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index c3013669b686..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 56244b905840..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index d2af46ddecb5..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index cee9234d1adf..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index 91768a2ec6b8..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index 383015e8528a..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index ab73c9f0c60a..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 07a81a711004..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 9303aeee359d..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index def4430f6c84..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index 43c9fb2394fb..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index ddbd04aed2dd..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index c8493ff4edad..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index de04176e8ae6..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index abee91e9acb3..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index e00a33a7b09a..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index 21286bfe6b55..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 8be5950b8534..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 7cdd39323a00..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index 07aa536eb55b..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index 3ca652925213..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 095a1a8d3ba8..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index eb8e313c54f5..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index 0f571e60fb7b..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index 3edbd149e622..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index 4cb141029174..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index 7a0b11c55c15..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 12d5d6f3076c..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 08da7e460b9b..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index 6ecd2e891d3b..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index 9e7e3f2e3069..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index bdd4f599ee6e..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index 1eb054744488..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index 06e4480f3129..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index f904325caf4e..000000000000 --- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/bottom_divider_glow.png b/packages/SystemUI/res/drawable-mdpi/bottom_divider_glow.png Binary files differindex 7d7868d2b9e7..ba25f653e566 100644 --- a/packages/SystemUI/res/drawable-mdpi/bottom_divider_glow.png +++ b/packages/SystemUI/res/drawable-mdpi/bottom_divider_glow.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png Binary files differdeleted file mode 100644 index 8dd3d4db68cb..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png Binary files differdeleted file mode 100644 index 2a9bf50c0320..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png Binary files differdeleted file mode 100644 index f59ba484d73b..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png Binary files differdeleted file mode 100644 index 12f16ddbaca9..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png Binary files differdeleted file mode 100644 index 649c89d9534b..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png Binary files differdeleted file mode 100644 index 95494e6132f1..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png Binary files differdeleted file mode 100644 index dfd92ee81159..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png Binary files differdeleted file mode 100644 index dcabf3f7aafa..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png Binary files differdeleted file mode 100644 index 41fc2e950448..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_orange.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png Binary files differdeleted file mode 100644 index 414be9de886a..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_red.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png Binary files differdeleted file mode 100644 index 398a08bf0710..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_bang_white.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png Binary files differdeleted file mode 100644 index b9172811a26a..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png Binary files differdeleted file mode 100644 index 2a05827ecdeb..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png Binary files differdeleted file mode 100644 index 86d11588478e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png Binary files differdeleted file mode 100644 index 076add96d58d..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png Binary files differdeleted file mode 100644 index 4bdae3c7d6fd..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png Binary files differdeleted file mode 100644 index 8353d9172097..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png Binary files differdeleted file mode 100644 index 91bd62ec2ed6..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png Binary files differdeleted file mode 100644 index a36d25d90758..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_charge_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png Binary files differdeleted file mode 100644 index a2e3cc968a28..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_battery_unknown.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png Binary files differdeleted file mode 100644 index 307398681a40..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_circle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png Binary files differdeleted file mode 100644 index 2a0bc596a092..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_hour.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png Binary files differdeleted file mode 100644 index 9b1cc58c324f..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_clock_minute.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png Binary files differindex 021ae6d9977c..0f7607b33eed 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_settings.png diff --git a/packages/SystemUI/res/drawable-mdpi/nav_background.9.png b/packages/SystemUI/res/drawable-mdpi/nav_background.9.png Binary files differindex 45e6e8fe5fc7..aa7415349ec9 100644 --- a/packages/SystemUI/res/drawable-mdpi/nav_background.9.png +++ b/packages/SystemUI/res/drawable-mdpi/nav_background.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png Binary files differdeleted file mode 100644 index 60dc3f21d4e5..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/recents_thumbnail_bg_dragging.9.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/search_light.png b/packages/SystemUI/res/drawable-mdpi/search_light.png Binary files differindex fb990617d032..7a70984378ce 100644 --- a/packages/SystemUI/res/drawable-mdpi/search_light.png +++ b/packages/SystemUI/res/drawable-mdpi/search_light.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png Binary files differdeleted file mode 100644 index edcb1b3d9cdc..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png Binary files differdeleted file mode 100644 index 8e0ec0f47c52..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png Binary files differdeleted file mode 100644 index b1b675bf492a..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png Binary files differdeleted file mode 100644 index 868bbbc28a1e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png Binary files differdeleted file mode 100644 index 890129e94b0b..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png Binary files differdeleted file mode 100644 index 86279af539d9..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png Binary files differdeleted file mode 100644 index de2aa4e5c5b1..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png Binary files differdeleted file mode 100644 index c008d6f4c95c..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png Binary files differdeleted file mode 100644 index 0c637935729e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png Binary files differdeleted file mode 100644 index c16c289178d7..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png Binary files differdeleted file mode 100644 index f4f59b40d819..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png Binary files differdeleted file mode 100644 index 1d2c557ae36e..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png Binary files differdeleted file mode 100644 index ebf78887b00c..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png Binary files differdeleted file mode 100644 index b10072861036..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png Binary files differdeleted file mode 100644 index 8b8e872e2909..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png Binary files differdeleted file mode 100644 index de78a9ce4f9b..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_charge_anim85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index e5a8f9531dc5..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index c1c2b5c79b24..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 421eee828820..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index bfd249491e6c..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index b1af67862c30..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index 9ad245bb532a..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 69a1a970bd6b..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index d86567348f92..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index 6bd3189e4dfb..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index f7f0e9396f65..000000000000 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png Binary files differindex 2e24f6f4f381..61d75110ca38 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png diff --git a/packages/SystemUI/res/drawable-mdpi/status_background.9.png b/packages/SystemUI/res/drawable-mdpi/status_background.9.png Binary files differindex 49076d315c3a..b79a6d907423 100644 --- a/packages/SystemUI/res/drawable-mdpi/status_background.9.png +++ b/packages/SystemUI/res/drawable-mdpi/status_background.9.png diff --git a/packages/SystemUI/res/drawable-mdpi/top_divider_glow.png b/packages/SystemUI/res/drawable-mdpi/top_divider_glow.png Binary files differindex f93da095dda8..53d85de10ba0 100644 --- a/packages/SystemUI/res/drawable-mdpi/top_divider_glow.png +++ b/packages/SystemUI/res/drawable-mdpi/top_divider_glow.png diff --git a/packages/SystemUI/res/drawable-xhdpi/bottom_divider_glow.png b/packages/SystemUI/res/drawable-xhdpi/bottom_divider_glow.png Binary files differindex bbcea9eb30f1..0b012b48f261 100644 --- a/packages/SystemUI/res/drawable-xhdpi/bottom_divider_glow.png +++ b/packages/SystemUI/res/drawable-xhdpi/bottom_divider_glow.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png Binary files differdeleted file mode 100644 index ff3bdf0d1356..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png Binary files differdeleted file mode 100644 index 8bc6d17362b6..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png Binary files differdeleted file mode 100644 index 39fccc88febd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png Binary files differdeleted file mode 100644 index 70829a10dbdd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png Binary files differdeleted file mode 100644 index ebd97c808f31..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png Binary files differdeleted file mode 100644 index 9d5be12bc47d..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png Binary files differdeleted file mode 100644 index 1ffa24579cf8..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png Binary files differdeleted file mode 100644 index b6aebe6fbe6c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png Binary files differdeleted file mode 100644 index 28ec7a86a093..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_orange.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png Binary files differdeleted file mode 100644 index 432b496836e4..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_red.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png Binary files differdeleted file mode 100644 index 9ed63f380ea3..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_bang_white.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png Binary files differdeleted file mode 100644 index 1ecedca5ca33..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png Binary files differdeleted file mode 100644 index 37cb7c4c8f43..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png Binary files differdeleted file mode 100644 index 1a595edc2be2..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png Binary files differdeleted file mode 100644 index e36e68cb5f78..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png Binary files differdeleted file mode 100644 index e58f9c041623..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png Binary files differdeleted file mode 100644 index c7fafa422d7e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png Binary files differdeleted file mode 100644 index 5dcec0ece294..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png Binary files differdeleted file mode 100644 index 6e8197482f57..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_charge_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png Binary files differdeleted file mode 100644 index 1db2eb3323f1..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_battery_unknown.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png Binary files differdeleted file mode 100644 index 72c587d3379c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_circle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png Binary files differdeleted file mode 100644 index d18dbd9ff75e..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_hour.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png Binary files differdeleted file mode 100644 index 31230af0afa0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_clock_minute.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png Binary files differindex e888ac237fca..4ce9460fdebc 100644 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_settings.png diff --git a/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png b/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png Binary files differindex 152e4aca6508..3b521959ffea 100644 --- a/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png +++ b/packages/SystemUI/res/drawable-xhdpi/nav_background.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png Binary files differdeleted file mode 100644 index 79d1b3c6b4ff..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/recents_thumbnail_bg_dragging.9.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/search_light.png b/packages/SystemUI/res/drawable-xhdpi/search_light.png Binary files differindex 438970767456..e2aed092dc9e 100644 --- a/packages/SystemUI/res/drawable-xhdpi/search_light.png +++ b/packages/SystemUI/res/drawable-xhdpi/search_light.png diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png Binary files differdeleted file mode 100644 index 8ea54eee32ec..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png Binary files differdeleted file mode 100644 index 877abf42a3f0..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png Binary files differdeleted file mode 100644 index 94605c9c726c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png Binary files differdeleted file mode 100644 index c4b77ec07659..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png Binary files differdeleted file mode 100644 index 9983d60cf6d8..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png Binary files differdeleted file mode 100644 index de09dc6f5217..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png Binary files differdeleted file mode 100644 index 99908696f08c..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png Binary files differdeleted file mode 100644 index 7a630f93f80b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png Binary files differdeleted file mode 100644 index 8a0a50f8191f..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png Binary files differdeleted file mode 100644 index 58ff765fa81b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png Binary files differdeleted file mode 100644 index ca1484104bc9..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png Binary files differdeleted file mode 100644 index 9b1a47cb1c84..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png Binary files differdeleted file mode 100644 index dd0066817740..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png Binary files differdeleted file mode 100644 index 556c7107407b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png Binary files differdeleted file mode 100644 index b87eb8782613..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png Binary files differdeleted file mode 100644 index fe7c1afe4c78..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_charge_anim85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index f64d58236b32..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index 31f5b90159bd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 881d5e83fad5..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index 2d80c4d4a202..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index ad85c83e6c48..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index bde43c6e88bd..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 914ac495de90..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index c83e9fe41495..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index 48bca909572b..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index 155143404c42..000000000000 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png Binary files differindex a7f001760eec..192d3f7bbad8 100644 --- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png +++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png diff --git a/packages/SystemUI/res/drawable-xhdpi/status_background.9.png b/packages/SystemUI/res/drawable-xhdpi/status_background.9.png Binary files differindex 75ec8f5d5d1b..87c641b06515 100644 --- a/packages/SystemUI/res/drawable-xhdpi/status_background.9.png +++ b/packages/SystemUI/res/drawable-xhdpi/status_background.9.png diff --git a/packages/SystemUI/res/drawable-xhdpi/top_divider_glow.png b/packages/SystemUI/res/drawable-xhdpi/top_divider_glow.png Binary files differindex 56b63d0ee7a5..d4526c0a6a3f 100644 --- a/packages/SystemUI/res/drawable-xhdpi/top_divider_glow.png +++ b/packages/SystemUI/res/drawable-xhdpi/top_divider_glow.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_0.png Binary files differdeleted file mode 100644 index 6ddf734beb5e..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_100.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_100.png Binary files differdeleted file mode 100644 index c04dc4b7db35..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png Binary files differdeleted file mode 100644 index e1e1b2e2f92e..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_28.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_28.png Binary files differdeleted file mode 100644 index 6ff8518a2cb9..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_43.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_43.png Binary files differdeleted file mode 100644 index c0e94f2da140..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_57.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_57.png Binary files differdeleted file mode 100644 index 175e14bc86f0..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_71.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_71.png Binary files differdeleted file mode 100644 index ca6ba47260a2..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_85.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_85.png Binary files differdeleted file mode 100644 index 95017e4fea6c..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png Binary files differdeleted file mode 100644 index 2b333d79f085..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_orange.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png Binary files differdeleted file mode 100644 index 4c71154030e2..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_red.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png Binary files differdeleted file mode 100644 index 976a36b294cd..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_bang_white.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png Binary files differdeleted file mode 100644 index 82d4806cdfd1..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_100.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_100.png Binary files differdeleted file mode 100644 index 7d11599aa466..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png Binary files differdeleted file mode 100644 index 3b36bb970828..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_28.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_28.png Binary files differdeleted file mode 100644 index d36bd5a1b275..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_43.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_43.png Binary files differdeleted file mode 100644 index a3f543aa4bd0..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_57.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_57.png Binary files differdeleted file mode 100644 index 0208baf415ad..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_71.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_71.png Binary files differdeleted file mode 100644 index ea46076756aa..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_85.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_85.png Binary files differdeleted file mode 100644 index 4cbfea69f3b1..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_charge_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_unknown.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_unknown.png Binary files differdeleted file mode 100644 index 5ae0221b3954..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_battery_unknown.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png Binary files differdeleted file mode 100644 index 849d547196b6..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_circle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png Binary files differdeleted file mode 100644 index 57dd8a65ccdd..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_hour.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png Binary files differdeleted file mode 100644 index a9b8ba56415a..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_clock_minute.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_settings.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_settings.png Binary files differindex d1a72bebefbf..74a78dca2dea 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_settings.png +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_settings.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png Binary files differindex cce2e062d949..b35183c84817 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png +++ b/packages/SystemUI/res/drawable-xxhdpi/nav_background.9.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png Binary files differdeleted file mode 100644 index c424ffefc258..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/recents_thumbnail_bg_dragging.9.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_light.png b/packages/SystemUI/res/drawable-xxhdpi/search_light.png Binary files differindex b4fa29777916..e5ef85d8fb1b 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/search_light.png +++ b/packages/SystemUI/res/drawable-xxhdpi/search_light.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_0.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_0.png Binary files differdeleted file mode 100644 index 2d916d7b7fd9..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_100.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_100.png Binary files differdeleted file mode 100644 index fe3c7506bab7..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png Binary files differdeleted file mode 100644 index a2bab6d58274..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_28.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_28.png Binary files differdeleted file mode 100644 index 224be03d419a..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_43.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_43.png Binary files differdeleted file mode 100644 index dabed32a8a60..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_57.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_57.png Binary files differdeleted file mode 100644 index 82d04c5754e6..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_71.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_71.png Binary files differdeleted file mode 100644 index 1d403c6fccf3..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_85.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_85.png Binary files differdeleted file mode 100644 index b917d37be165..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png Binary files differdeleted file mode 100644 index 1da84be163d4..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png Binary files differdeleted file mode 100644 index 17989b5f7c9f..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim100.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png Binary files differdeleted file mode 100644 index 8733bc36d866..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim15.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png Binary files differdeleted file mode 100644 index 54cc84740787..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim28.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png Binary files differdeleted file mode 100644 index 5d5ba2fc16bb..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim43.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png Binary files differdeleted file mode 100644 index 6a5035ee115c..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim57.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png Binary files differdeleted file mode 100644 index 82a891f93d19..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim71.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png Binary files differdeleted file mode 100644 index 399bb97446ce..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_charge_anim85.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0.png Binary files differdeleted file mode 100644 index 21daf5c16559..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0_fully.png Binary files differdeleted file mode 100644 index 3397570da08e..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_0_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1.png Binary files differdeleted file mode 100644 index 87039c5bf639..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1_fully.png Binary files differdeleted file mode 100644 index a21f3c4d8e2d..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_1_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2.png Binary files differdeleted file mode 100644 index 65b323f559fa..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2_fully.png Binary files differdeleted file mode 100644 index c5c35500a55b..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_2_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3.png Binary files differdeleted file mode 100644 index 801cb3cac528..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png Binary files differdeleted file mode 100644 index 149d22785a1c..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_3_fully.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png Binary files differdeleted file mode 100644 index 6edb37a8b377..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_disconnected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_idle.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_idle.png Binary files differdeleted file mode 100644 index 2b01e9b59bca..000000000000 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_data_wimax_signal_idle.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png Binary files differindex ad34d4948dd6..1e5f15fc8372 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png +++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_device_access_location_found.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/status_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/status_background.9.png Binary files differindex 679ca5d5c0e4..727c8040ddf0 100644 --- a/packages/SystemUI/res/drawable-xxhdpi/status_background.9.png +++ b/packages/SystemUI/res/drawable-xxhdpi/status_background.9.png diff --git a/packages/SystemUI/res/drawable/qs_sys_battery.xml b/packages/SystemUI/res/drawable/qs_sys_battery.xml deleted file mode 100644 index dd36aa53ee06..000000000000 --- a/packages/SystemUI/res/drawable/qs_sys_battery.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 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. -*/ ---> - -<level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:maxLevel="4" android:drawable="@drawable/ic_qs_battery_0" /> - <item android:maxLevel="15" android:drawable="@drawable/ic_qs_battery_15" /> - <item android:maxLevel="35" android:drawable="@drawable/ic_qs_battery_28" /> - <item android:maxLevel="49" android:drawable="@drawable/ic_qs_battery_43" /> - <item android:maxLevel="60" android:drawable="@drawable/ic_qs_battery_57" /> - <item android:maxLevel="75" android:drawable="@drawable/ic_qs_battery_71" /> - <item android:maxLevel="90" android:drawable="@drawable/ic_qs_battery_85" /> - <item android:maxLevel="100" android:drawable="@drawable/ic_qs_battery_100" /> -</level-list> diff --git a/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml b/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml deleted file mode 100644 index cee50811ac70..000000000000 --- a/packages/SystemUI/res/drawable/qs_sys_battery_charging.xml +++ /dev/null @@ -1,29 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 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. -*/ ---> - -<level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:maxLevel="4" android:drawable="@drawable/ic_qs_battery_charge_0" /> - <item android:maxLevel="15" android:drawable="@drawable/ic_qs_battery_charge_15" /> - <item android:maxLevel="35" android:drawable="@drawable/ic_qs_battery_charge_28" /> - <item android:maxLevel="49" android:drawable="@drawable/ic_qs_battery_charge_43" /> - <item android:maxLevel="60" android:drawable="@drawable/ic_qs_battery_charge_57" /> - <item android:maxLevel="75" android:drawable="@drawable/ic_qs_battery_charge_71" /> - <item android:maxLevel="90" android:drawable="@drawable/ic_qs_battery_charge_85" /> - <item android:maxLevel="100" android:drawable="@drawable/ic_qs_battery_charge_100" /> -</level-list> diff --git a/packages/SystemUI/res/drawable/stat_sys_battery.xml b/packages/SystemUI/res/drawable/stat_sys_battery.xml deleted file mode 100644 index 744ab93da9af..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_battery.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 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. -*/ ---> - -<level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_0" /> - <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_15" /> - <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_28" /> - <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_43" /> - <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_57" /> - <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_71" /> - <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_85" /> - <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_100" /> -</level-list> - diff --git a/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml b/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml deleted file mode 100644 index 6918eb21ed9d..000000000000 --- a/packages/SystemUI/res/drawable/stat_sys_battery_charge.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 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. -*/ ---> - -<level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:maxLevel="4" android:drawable="@drawable/stat_sys_battery_charge_anim0" /> - <item android:maxLevel="15" android:drawable="@drawable/stat_sys_battery_charge_anim15" /> - <item android:maxLevel="35" android:drawable="@drawable/stat_sys_battery_charge_anim28" /> - <item android:maxLevel="49" android:drawable="@drawable/stat_sys_battery_charge_anim43" /> - <item android:maxLevel="60" android:drawable="@drawable/stat_sys_battery_charge_anim57" /> - <item android:maxLevel="75" android:drawable="@drawable/stat_sys_battery_charge_anim71" /> - <item android:maxLevel="90" android:drawable="@drawable/stat_sys_battery_charge_anim85" /> - <item android:maxLevel="100" android:drawable="@drawable/stat_sys_battery_charge_anim100" /> -</level-list> - - diff --git a/packages/SystemUI/res/layout/quick_settings_tile_time.xml b/packages/SystemUI/res/layout/quick_settings_tile_time.xml deleted file mode 100644 index 910e1f63f16b..000000000000 --- a/packages/SystemUI/res/layout/quick_settings_tile_time.xml +++ /dev/null @@ -1,39 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 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. ---> -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:orientation="vertical"> - <AnalogClock - android:id="@+id/analog_clock" - android:layout_width="32dp" - android:layout_height="32dp" - android:layout_gravity="center" - android:layout_marginBottom="10dp" - android:dial="@drawable/ic_qs_clock_circle" - android:hand_hour="@drawable/ic_qs_clock_hour" - android:hand_minute="@drawable/ic_qs_clock_minute" - /> - <com.android.systemui.statusbar.policy.DateView - android:textAppearance="@style/TextAppearance.QuickSettings.TileView" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:gravity="center" - /> -</LinearLayout> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index ce9416286109..0bbdeade208a 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -19,7 +19,8 @@ <resources> <drawable name="notification_number_text_color">#ffffffff</drawable> <drawable name="ticker_background_color">#ff1d1d1d</drawable> - <drawable name="system_bar_background">#ff000000</drawable> + <drawable name="system_bar_background">@color/system_bar_background_opaque</drawable> + <color name="system_bar_background_opaque">#ff000000</color> <color name="system_bar_background_semi_transparent">#66000000</color> <!-- 40% black --> <color name="notification_panel_solid_background">#ff000000</color> <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable> diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index a08eb9b0a722..28c2772f5c9f 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -29,9 +29,11 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.BatteryManager; import android.os.Handler; +import android.os.PowerManager; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; -import android.util.Log; +import android.util.Slog; import android.view.View; import android.view.WindowManager; import android.widget.TextView; @@ -62,6 +64,8 @@ public class PowerUI extends SystemUI { AlertDialog mLowBatteryDialog; TextView mBatteryLevelTextView; + private long mScreenOffTime = -1; + public void start() { mLowBatteryAlertCloseLevel = mContext.getResources().getInteger( @@ -71,10 +75,14 @@ public class PowerUI extends SystemUI { mLowBatteryReminderLevels[1] = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); + final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); + // Register for Intent broadcasts for... IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(Intent.ACTION_POWER_CONNECTED); + filter.addAction(Intent.ACTION_SCREEN_OFF); + filter.addAction(Intent.ACTION_SCREEN_ON); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); } @@ -126,19 +134,19 @@ public class PowerUI extends SystemUI { int bucket = findBatteryLevelBucket(mBatteryLevel); if (DEBUG) { - Log.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel + Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel + " .. " + mLowBatteryReminderLevels[0] + " .. " + mLowBatteryReminderLevels[1]); - Log.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel); - Log.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus); - Log.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType); - Log.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger); - Log.d(TAG, "bucket " + oldBucket + " --> " + bucket); - Log.d(TAG, "plugged " + oldPlugged + " --> " + plugged); + Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel); + Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus); + Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType); + Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger); + Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket); + Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged); } if (oldInvalidCharger == 0 && mInvalidCharger != 0) { - Log.d(TAG, "showing invalid charger warning"); + Slog.d(TAG, "showing invalid charger warning"); showInvalidChargerDialog(); return; } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) { @@ -163,21 +171,25 @@ public class PowerUI extends SystemUI { } else if (mBatteryLevelTextView != null) { showLowBatteryWarning(); } + } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { + mScreenOffTime = SystemClock.elapsedRealtime(); + } else if (Intent.ACTION_SCREEN_ON.equals(action)) { + mScreenOffTime = -1; } else { - Log.w(TAG, "unknown intent: " + intent); + Slog.w(TAG, "unknown intent: " + intent); } } }; void dismissLowBatteryWarning() { if (mLowBatteryDialog != null) { - Log.i(TAG, "closing low battery warning: level=" + mBatteryLevel); + Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel); mLowBatteryDialog.dismiss(); } } void showLowBatteryWarning() { - Log.i(TAG, + Slog.i(TAG, ((mBatteryLevelTextView == null) ? "showing" : "updating") + " low battery warning: level=" + mBatteryLevel + " [" + findBatteryLevelBucket(mBatteryLevel) + "]"); @@ -233,11 +245,23 @@ public class PowerUI extends SystemUI { } void playLowBatterySound() { + final ContentResolver cr = mContext.getContentResolver(); + + final int silenceAfter = Settings.Global.getInt(cr, + Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0); + final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime; + if (silenceAfter > 0 + && mScreenOffTime > 0 + && offTime > silenceAfter) { + Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter + + "ms): not waking up the user with low battery sound"); + return; + } + if (DEBUG) { - Log.i(TAG, "playing low battery sound. WOMP-WOMP!"); + Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated } - final ContentResolver cr = mContext.getContentResolver(); if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) { final String soundPath = Settings.Global.getString(cr, Settings.Global.LOW_BATTERY_SOUND); @@ -261,7 +285,7 @@ public class PowerUI extends SystemUI { } void showInvalidChargerDialog() { - Log.d(TAG, "showing invalid charger dialog"); + Slog.d(TAG, "showing invalid charger dialog"); dismissLowBatteryWarning(); @@ -301,6 +325,17 @@ public class PowerUI extends SystemUI { pw.println(Integer.toString(mPlugType)); pw.print("mInvalidCharger="); pw.println(Integer.toString(mInvalidCharger)); + pw.print("mScreenOffTime="); + pw.print(mScreenOffTime); + if (mScreenOffTime >= 0) { + pw.print(" ("); + pw.print(SystemClock.elapsedRealtime() - mScreenOffTime); + pw.print(" ago)"); + } + pw.println(); + pw.print("soundTimeout="); + pw.println(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0)); pw.print("bucket: "); pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel))); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 932fe208c4fc..6a2bc5ff1739 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -570,12 +570,14 @@ public abstract class BaseStatusBar extends SystemUI implements if (DEBUG) Log.d(TAG, "opening search panel"); if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) { mSearchPanelView.show(true, true); + onShowSearchPanel(); } break; case MSG_CLOSE_SEARCH_PANEL: if (DEBUG) Log.d(TAG, "closing search panel"); if (mSearchPanelView != null && mSearchPanelView.isShowing()) { mSearchPanelView.show(false, true); + onHideSearchPanel(); } break; } @@ -607,6 +609,12 @@ public abstract class BaseStatusBar extends SystemUI implements protected void workAroundBadLayerDrawableOpacity(View v) { } + protected void onHideSearchPanel() { + } + + protected void onShowSearchPanel() { + } + public boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) { int minHeight = mContext.getResources().getDimensionPixelSize(R.dimen.notification_min_height); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java index 16fe1aa15922..8819c60aee07 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java @@ -35,7 +35,7 @@ import java.io.PrintWriter; */ public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks { private static final String TAG = "SystemBars"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private static final int WAIT_FOR_BARS_TO_DIE = 500; // manages the implementation coming from the remote process diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java index 7b1df91e6bd6..1c8702abdd1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java @@ -71,7 +71,7 @@ public class BarTransitions { mOpaque = 0xff0000ff; mSemiTransparent = 0x7f0000ff; } else { - mOpaque = res.getColor(R.drawable.system_bar_background); + mOpaque = res.getColor(R.color.system_bar_background_opaque); mSemiTransparent = res.getColor(R.color.system_bar_background_semi_transparent); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 6e5336384d44..d1c4109c4c92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -37,10 +37,10 @@ import android.view.Display; import android.view.MotionEvent; import android.view.Surface; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener; import android.widget.ImageView; import android.widget.LinearLayout; @@ -89,26 +89,31 @@ public class NavigationBarView extends LinearLayout { // used to disable the camera icon in navbar when disabled by DPM private boolean mCameraDisabledByDpm; + // simplified click handler to be used when device is in accessibility mode + private final OnClickListener mAccessibilityClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + if (v.getId() == R.id.camera_button) { + KeyguardTouchDelegate.getInstance(getContext()).launchCamera(); + } else if (v.getId() == R.id.search_light) { + KeyguardTouchDelegate.getInstance(getContext()).showAssistant(); + } + } + }; + private final OnTouchListener mCameraTouchListener = new OnTouchListener() { @Override public boolean onTouch(View cameraButtonView, MotionEvent event) { - View searchLight = getSearchLight(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // disable search gesture while interacting with camera mDelegateHelper.setDisabled(true); - cameraButtonView.animate().alpha(0.0f).setDuration(CAMERA_BUTTON_FADE_DURATION); - if (searchLight != null) { - searchLight.animate().alpha(0.0f).setDuration(CAMERA_BUTTON_FADE_DURATION); - } + transitionCameraAndSearchButtonAlpha(0.0f); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mDelegateHelper.setDisabled(false); - cameraButtonView.animate().alpha(1.0f).setDuration(CAMERA_BUTTON_FADE_DURATION); - if (searchLight != null) { - searchLight.animate().alpha(1.0f).setDuration(CAMERA_BUTTON_FADE_DURATION); - } + transitionCameraAndSearchButtonAlpha(1.0f); break; } return KeyguardTouchDelegate.getInstance(getContext()).dispatch(event); @@ -158,6 +163,17 @@ public class NavigationBarView extends LinearLayout { watchForDevicePolicyChanges(); } + protected void transitionCameraAndSearchButtonAlpha(float alpha) { + View cameraButtonView = getCameraButton(); + if (cameraButtonView != null) { + cameraButtonView.animate().alpha(alpha).setDuration(CAMERA_BUTTON_FADE_DURATION); + } + View searchLight = getSearchLight(); + if (searchLight != null) { + searchLight.animate().alpha(alpha).setDuration(CAMERA_BUTTON_FADE_DURATION); + } + } + private void watchForDevicePolicyChanges() { final IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); @@ -388,44 +404,49 @@ public class NavigationBarView extends LinearLayout { mCurrentView = mRotatedViews[Surface.ROTATION_0]; + watchForAccessibilityChanges(); + } - final AccessibilityManager accessibilityManager = + private void watchForAccessibilityChanges() { + final AccessibilityManager am = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - if (accessibilityManager.isEnabled() && accessibilityManager.isTouchExplorationEnabled()) { - // In accessibility mode, we add a simple click handler since swipe is tough to - // trigger near screen edges. - View camera = getCameraButton(); - View searchLight = getSearchLight(); - if (camera != null || searchLight != null) { - OnClickListener listener = new OnClickListener() { - @Override - public void onClick(View v) { - launchForAccessibilityClick(v); - } - }; - if (camera != null) { - camera.setOnClickListener(listener); - } - if (searchLight != null) { - searchLight.setOnClickListener(listener); - } + + // Set the initial state + enableAccessibility(am.isTouchExplorationEnabled()); + + // Watch for changes + am.addTouchExplorationStateChangeListener(new TouchExplorationStateChangeListener() { + @Override + public void onTouchExplorationStateChanged(boolean enabled) { + enableAccessibility(enabled); } - } else { - // Add a touch handler for camera icon for all view orientations. - for (int i = 0; i < mRotatedViews.length; i++) { - View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); - if (cameraButton != null) { - cameraButton.setOnTouchListener(mCameraTouchListener); - } + }); + } + + private void enableAccessibility(boolean touchEnabled) { + Log.v(TAG, "touchEnabled:" + touchEnabled); + + // Add a touch handler or accessibility click listener for camera and search buttons + // for all view orientations. + final OnClickListener onClickListener = touchEnabled ? mAccessibilityClickListener : null; + final OnTouchListener onTouchListener = touchEnabled ? null : mCameraTouchListener; + boolean hasCamera = false; + for (int i = 0; i < mRotatedViews.length; i++) { + final View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button); + final View searchLight = mRotatedViews[i].findViewById(R.id.search_light); + if (cameraButton != null) { + hasCamera = true; + cameraButton.setOnTouchListener(onTouchListener); + cameraButton.setOnClickListener(onClickListener); + } + if (searchLight != null) { + searchLight.setOnClickListener(onClickListener); } } - } - - protected void launchForAccessibilityClick(View v) { - if (v == getCameraButton()) { - KeyguardTouchDelegate.getInstance(getContext()).launchCamera(); - } else if (v == getSearchLight()) { - KeyguardTouchDelegate.getInstance(getContext()).showAssistant(); + if (hasCamera) { + // Warm up KeyguardTouchDelegate so it's ready by the time the camera button is touched. + // This will connect to KeyguardService so that touch events are processed. + KeyguardTouchDelegate.getInstance(mContext); } } 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 93a9b9299002..3ddcb1b03b51 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -113,7 +113,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { public static final boolean DUMPTRUCK = true; // extra dumpsys info public static final boolean DEBUG_GESTURES = false; - public static final boolean DEBUG_WINDOW_STATE = true; + public static final boolean DEBUG_WINDOW_STATE = false; public static final boolean SETTINGS_DRAG_SHORTCUT = true; @@ -647,6 +647,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } @Override + protected void onShowSearchPanel() { + if (mNavigationBarView != null) { + mNavigationBarView.transitionCameraAndSearchButtonAlpha(0.0f); + } + } + + @Override + protected void onHideSearchPanel() { + if (mNavigationBarView != null) { + mNavigationBarView.transitionCameraAndSearchButtonAlpha(1.0f); + } + } + + @Override protected View getStatusBarView() { return mStatusBarView; } @@ -1923,10 +1937,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } private void checkBarMode(int mode, int windowState, BarTransitions transitions) { - final boolean imeVisible = (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0; - final int finalMode = imeVisible ? MODE_OPAQUE : mode; final boolean anim = (mScreenOn == null || mScreenOn) && windowState != WINDOW_STATE_HIDDEN; - transitions.transitionTo(finalMode, anim); + transitions.transitionTo(mode, anim); } private final Runnable mCheckBarModes = new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 36ba4d9d3f8d..5423bb639044 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -107,9 +107,6 @@ class QuickSettings { private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask; private AsyncTask<Void, Void, Pair<Boolean, Boolean>> mQueryCertTask; - private LevelListDrawable mBatteryLevels; - private LevelListDrawable mChargingBatteryLevels; - boolean mTilesSetUp = false; boolean mUseDefaultAvatar = false; @@ -134,11 +131,6 @@ class QuickSettings { mHandler = new Handler(); - Resources r = mContext.getResources(); - mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery); - mChargingBatteryLevels = - (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging); - IntentFilter filter = new IntentFilter(); filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); @@ -366,26 +358,6 @@ class QuickSettings { parent.addView(brightnessTile); mDynamicSpannedTiles.add(brightnessTile); - // Time tile - /* - QuickSettingsTileView timeTile = (QuickSettingsTileView) - inflater.inflate(R.layout.quick_settings_tile, parent, false); - timeTile.setContent(R.layout.quick_settings_tile_time, inflater); - timeTile.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // Quick. Clock. Quick. Clock. Quick. Clock. - startSettingsActivity(Intent.ACTION_QUICK_CLOCK); - } - }); - mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() { - @Override - public void refreshView(QuickSettingsTileView view, State alarmState) {} - }); - parent.addView(timeTile); - mDynamicSpannedTiles.add(timeTile); - */ - // Settings tile final QuickSettingsBasicTile settingsTile = new QuickSettingsBasicTile(mContext); settingsTile.setImageResource(R.drawable.ic_qs_settings); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java index 9d0418dab44d..e6823ac7d2ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java @@ -34,6 +34,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.text.TextUtils; +import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; @@ -308,6 +309,7 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, refreshBluetoothTile(); refreshBrightnessTile(); refreshRotationLockTile(); + refreshRssiTile(); } // Settings @@ -501,6 +503,14 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, } } + void refreshRssiTile() { + if (mRSSITile != null) { + // We reinflate the original view due to potential styling changes that may have + // taken place due to a configuration change. + mRSSITile.reinflateContent(LayoutInflater.from(mContext)); + } + } + // Bluetooth void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { mBluetoothTile = view; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java index 9cff242924c1..3d520f7e400c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.content.Context; import android.util.AttributeSet; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; @@ -26,13 +27,16 @@ import android.widget.FrameLayout; * */ class QuickSettingsTileView extends FrameLayout { + private static final String TAG = "QuickSettingsTileView"; + private int mContentLayoutId; private int mColSpan; private int mRowSpan; public QuickSettingsTileView(Context context, AttributeSet attrs) { super(context, attrs); + mContentLayoutId = -1; mColSpan = 1; mRowSpan = 1; } @@ -46,9 +50,19 @@ class QuickSettingsTileView extends FrameLayout { } void setContent(int layoutId, LayoutInflater inflater) { + mContentLayoutId = layoutId; inflater.inflate(layoutId, this); } + void reinflateContent(LayoutInflater inflater) { + if (mContentLayoutId != -1) { + removeAllViews(); + setContent(mContentLayoutId, inflater); + } else { + Log.e(TAG, "Not reinflating content: No layoutId set"); + } + } + @Override public void setVisibility(int vis) { if (QuickSettings.DEBUG_GONE_TILES) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index 575b44ebce6f..6db9bc38b173 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -21,19 +21,12 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.systemui.R; import java.util.ArrayList; public class BatteryController extends BroadcastReceiver { private static final String TAG = "StatusBar.BatteryController"; - private Context mContext; - private ArrayList<ImageView> mIconViews = new ArrayList<ImageView>(); - private ArrayList<TextView> mLabelViews = new ArrayList<TextView>(); private ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<BatteryStateChangeCallback>(); @@ -43,21 +36,11 @@ public class BatteryController extends BroadcastReceiver { } public BatteryController(Context context) { - mContext = context; - IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); context.registerReceiver(this, filter); } - public void addIconView(ImageView v) { - mIconViews.add(v); - } - - public void addLabelView(TextView v) { - mLabelViews.add(v); - } - public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); } @@ -77,24 +60,6 @@ public class BatteryController extends BroadcastReceiver { break; } - final int icon = plugged ? R.drawable.stat_sys_battery_charge - : R.drawable.stat_sys_battery; - - int N = mIconViews.size(); - for (int i=0; i<N; i++) { - ImageView v = mIconViews.get(i); - v.setImageResource(icon); - v.setImageLevel(level); - v.setContentDescription(mContext.getString(R.string.accessibility_battery_level, - level)); - } - N = mLabelViews.size(); - for (int i=0; i<N; i++) { - TextView v = mLabelViews.get(i); - v.setText(mContext.getString(R.string.status_bar_settings_battery_meter_format, - level)); - } - for (BatteryStateChangeCallback cb : mChangeCallbacks) { cb.onBatteryLevelChanged(level, plugged); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java index 16e2e079d2ab..b7f3cfe9ce16 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java @@ -50,7 +50,8 @@ public class DateView extends TextView { || Intent.ACTION_TIME_CHANGED.equals(action) || Intent.ACTION_TIMEZONE_CHANGED.equals(action) || Intent.ACTION_LOCALE_CHANGED.equals(action)) { - if (Intent.ACTION_LOCALE_CHANGED.equals(action)) { + if (Intent.ACTION_LOCALE_CHANGED.equals(action) + || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { // need to get a fresh date format mDateFormat = null; } diff --git a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml index 6dc7e351acad..97d700169be2 100644 --- a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml +++ b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml @@ -19,7 +19,7 @@ --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/wallpaper_cropper" + android:id="@+id/wallpaper_root" android:layout_width="match_parent" android:layout_height="match_parent"> <com.android.wallpapercropper.CropView diff --git a/packages/SystemUI/res/drawable/ic_qs_battery.xml b/packages/WallpaperCropper/res/values-sw600dp/config.xml index 4e2a265890a9..62342dcc2f35 100644 --- a/packages/SystemUI/res/drawable/ic_qs_battery.xml +++ b/packages/WallpaperCropper/res/values-sw600dp/config.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project +<!-- Copyright (C) 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. @@ -13,8 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. --> -<clip - xmlns:android="http://schemas.android.com/apk/res/android" - android:drawable="@drawable/stat_sys_battery_100" - android:clipOrientation="vertical" - android:gravity="bottom" /> +<resources> + <bool name="allow_rotation">true</bool> +</resources> diff --git a/packages/WallpaperCropper/res/values/config.xml b/packages/WallpaperCropper/res/values/config.xml new file mode 100644 index 000000000000..1b2419073502 --- /dev/null +++ b/packages/WallpaperCropper/res/values/config.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 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> + <bool name="allow_rotation">false</bool> +</resources> diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/CropView.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/CropView.java index ecebd64227ba..b4e715ca24d5 100644 --- a/packages/WallpaperCropper/src/com/android/wallpapercropper/CropView.java +++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/CropView.java @@ -22,8 +22,8 @@ import android.graphics.RectF; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ScaleGestureDetector; -import android.view.ViewConfiguration; import android.view.ScaleGestureDetector.OnScaleGestureListener; +import android.view.ViewConfiguration; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; @@ -44,6 +44,7 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { public interface TouchCallback { void onTouchDown(); void onTap(); + void onTouchUp(); } public CropView(Context context) { @@ -140,12 +141,12 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { public void onScaleEnd(ScaleGestureDetector detector) { } - public void moveToUpperLeft() { + public void moveToLeft() { if (getWidth() == 0 || getHeight() == 0) { final ViewTreeObserver observer = getViewTreeObserver(); observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { public void onGlobalLayout() { - moveToUpperLeft(); + moveToLeft(); getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); @@ -154,7 +155,6 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { getEdgesHelper(edges); final float scale = mRenderer.scale; mRenderer.centerX += Math.ceil(edges.left / scale); - mRenderer.centerY += Math.ceil(edges.top / scale); } public void setTouchEnabled(boolean enabled) { @@ -197,11 +197,13 @@ public class CropView extends TiledImageView implements OnScaleGestureListener { float squaredDist = (mFirstX - x) * (mFirstX - x) + (mFirstY - y) * (mFirstY - y); float slop = config.getScaledTouchSlop() * config.getScaledTouchSlop(); long now = System.currentTimeMillis(); - // only do this if it's a small movement - if (mTouchCallback != null && - squaredDist < slop && + if (mTouchCallback != null) { + // only do this if it's a small movement + if (squaredDist < slop && now < mTouchDownTime + ViewConfiguration.getTapTimeout()) { - mTouchCallback.onTap(); + mTouchCallback.onTap(); + } + mTouchCallback.onTouchUp(); } } diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java index af486521de91..710e8e470d4d 100644 --- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java +++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java @@ -75,6 +75,9 @@ public class WallpaperCropActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); init(); + if (!enableRotation()) { + setRequestedOrientation(Configuration.ORIENTATION_PORTRAIT); + } } protected void init() { @@ -99,6 +102,12 @@ public class WallpaperCropActivity extends Activity { cropImageAndSetWallpaper(imageUri, null, finishActivityWhenDone); } }); + getWindow().addPrivateFlags( + WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR); + } + + public boolean enableRotation() { + return getResources().getBoolean(R.bool.allow_rotation); } public static String getSharedPreferencesKey() { @@ -162,7 +171,6 @@ public class WallpaperCropActivity extends Activity { } protected void setWallpaper(String filePath, final boolean finishActivityWhenDone) { - BitmapCropTask cropTask = new BitmapCropTask(this, filePath, null, 0, 0, true, false, null); final Point bounds = cropTask.getImageBounds(); @@ -200,7 +208,7 @@ public class WallpaperCropActivity extends Activity { } } }; - BitmapCropTask cropTask = new BitmapCropTask(res, resId, + BitmapCropTask cropTask = new BitmapCropTask(this, res, resId, crop, outSize.x, outSize.y, true, false, onEndCrop); cropTask.execute(); @@ -213,9 +221,11 @@ public class WallpaperCropActivity extends Activity { protected void cropImageAndSetWallpaper(Uri uri, OnBitmapCroppedHandler onBitmapCroppedHandler, final boolean finishActivityWhenDone) { - // Get the crop + // Get the crop Point inSize = mCropView.getSourceDimensions(); + boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR; + Point minDims = new Point(); Point maxDims = new Point(); Display d = getWindowManager().getDefaultDisplay(); @@ -226,12 +236,12 @@ public class WallpaperCropActivity extends Activity { int maxDim = Math.max(maxDims.x, maxDims.y); final int minDim = Math.min(minDims.x, minDims.y); - int defaultWidth; + int defaultWallpaperWidth; if (isScreenLarge(getResources())) { - defaultWidth = (int) (maxDim * + defaultWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim)); } else { - defaultWidth = Math.max((int) + defaultWallpaperWidth = Math.max((int) (minDim * WALLPAPER_SCREENS_SPAN), maxDim); } @@ -256,12 +266,17 @@ public class WallpaperCropActivity extends Activity { // ADJUST CROP WIDTH // Extend the crop all the way to the right, for parallax - float extraSpaceToRight = inSize.x - cropRect.right; + // (or all the way to the left, in RTL) + float extraSpace = ltr ? inSize.x - cropRect.right : cropRect.left; // Cap the amount of extra width - float maxExtraSpace = defaultWidth / cropScale - cropRect.width(); - extraSpaceToRight = Math.min(extraSpaceToRight, maxExtraSpace); + float maxExtraSpace = defaultWallpaperWidth / cropScale - cropRect.width(); + extraSpace = Math.min(extraSpace, maxExtraSpace); - cropRect.right += extraSpaceToRight; + if (ltr) { + cropRect.right += extraSpace; + } else { + cropRect.left -= extraSpace; + } // ADJUST CROP HEIGHT if (isPortrait) { @@ -287,7 +302,7 @@ public class WallpaperCropActivity extends Activity { } } }; - BitmapCropTask cropTask = new BitmapCropTask(uri, + BitmapCropTask cropTask = new BitmapCropTask(this, uri, cropRect, outWidth, outHeight, true, false, onEndCrop); if (onBitmapCroppedHandler != null) { cropTask.setOnBitmapCropped(onBitmapCroppedHandler); @@ -299,7 +314,7 @@ public class WallpaperCropActivity extends Activity { public void onBitmapCropped(byte[] imageBytes); } - protected class BitmapCropTask extends AsyncTask<Void, Void, Boolean> { + protected static class BitmapCropTask extends AsyncTask<Void, Void, Boolean> { Uri mInUri = null; Context mContext; String mInFilePath; @@ -309,7 +324,6 @@ public class WallpaperCropActivity extends Activity { RectF mCropBounds = null; int mOutWidth, mOutHeight; int mRotation = 0; // for now - protected final WallpaperManager mWPManager; String mOutputFormat = "jpg"; // for now boolean mSetWallpaper; boolean mSaveCroppedBitmap; @@ -324,7 +338,6 @@ public class WallpaperCropActivity extends Activity { boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mContext = c; mInFilePath = filePath; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } @@ -332,24 +345,23 @@ public class WallpaperCropActivity extends Activity { RectF cropBounds, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { mInImageBytes = imageBytes; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } - public BitmapCropTask(Uri inUri, + public BitmapCropTask(Context c, Uri inUri, RectF cropBounds, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { + mContext = c; mInUri = inUri; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } - public BitmapCropTask(Resources res, int inResId, + public BitmapCropTask(Context c, Resources res, int inResId, RectF cropBounds, int outWidth, int outHeight, boolean setWallpaper, boolean saveCroppedBitmap, Runnable onEndRunnable) { + mContext = c; mInResId = inResId; mResources = res; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); init(cropBounds, outWidth, outHeight, setWallpaper, saveCroppedBitmap, onEndRunnable); } @@ -385,7 +397,7 @@ public class WallpaperCropActivity extends Activity { try { if (mInUri != null) { mInStream = new BufferedInputStream( - getContentResolver().openInputStream(mInUri)); + mContext.getContentResolver().openInputStream(mInUri)); } else if (mInFilePath != null) { mInStream = mContext.openFileInput(mInFilePath); } else if (mInImageBytes != null) { @@ -426,16 +438,17 @@ public class WallpaperCropActivity extends Activity { regenerateInputStream(); - if (mNoCrop && mInStream != null) { + WallpaperManager wallpaperManager = null; + if (mSetWallpaper) { + wallpaperManager = WallpaperManager.getInstance(mContext.getApplicationContext()); + } + if (mSetWallpaper && mNoCrop && mInStream != null) { try { - mWPManager.setStream(mInStream); + wallpaperManager.setStream(mInStream); } catch (IOException e) { Log.w(LOGTAG, "cannot write stream to wallpaper", e); failure = true; } - if (mOnEndRunnable != null) { - mOnEndRunnable.run(); - } return !failure; } if (mInStream != null) { @@ -509,7 +522,9 @@ public class WallpaperCropActivity extends Activity { (int) returnRect.height(), Bitmap.Config.ARGB_8888); if (tmp != null) { Canvas c = new Canvas(tmp); - c.drawBitmap(crop, m, new Paint()); + Paint p = new Paint(); + p.setFilterBitmap(true); + c.drawBitmap(crop, m, p); crop = tmp; } } else if (mRotation > 0) { @@ -534,26 +549,18 @@ public class WallpaperCropActivity extends Activity { ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { // If we need to set to the wallpaper, set it - if (mSetWallpaper && mWPManager != null) { - if (mWPManager == null) { - Log.w(LOGTAG, "no wallpaper manager"); - failure = true; - } else { - try { - byte[] outByteArray = tmpOut.toByteArray(); - mWPManager.setStream(new ByteArrayInputStream(outByteArray)); - if (mOnBitmapCroppedHandler != null) { - mOnBitmapCroppedHandler.onBitmapCropped(outByteArray); - } - } catch (IOException e) { - Log.w(LOGTAG, "cannot write stream to wallpaper", e); - failure = true; + if (mSetWallpaper && wallpaperManager != null) { + try { + byte[] outByteArray = tmpOut.toByteArray(); + wallpaperManager.setStream(new ByteArrayInputStream(outByteArray)); + if (mOnBitmapCroppedHandler != null) { + mOnBitmapCroppedHandler.onBitmapCropped(outByteArray); } + } catch (IOException e) { + Log.w(LOGTAG, "cannot write stream to wallpaper", e); + failure = true; } } - if (mOnEndRunnable != null) { - mOnEndRunnable.run(); - } } else { Log.w(LOGTAG, "cannot compress bitmap"); failure = true; @@ -569,8 +576,9 @@ public class WallpaperCropActivity extends Activity { @Override protected void onPostExecute(Boolean result) { - setResult(Activity.RESULT_OK); - finish(); + if (mOnEndRunnable != null) { + mOnEndRunnable.run(); + } } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index d8af0072e98b..eba689d62338 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -2338,6 +2338,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { originalView.getWindowToken()); if (helper != null) { helper.setPresenterCallback(mContextMenuCallback); + } else if (mContextMenuHelper != null) { + // No menu to show, but if we have a menu currently showing it just became blank. + // Close it. + mContextMenuHelper.dismiss(); } mContextMenuHelper = helper; return helper != null; diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index dd4f3d1f9be3..225bb94ea203 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -163,7 +163,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { */ static final int SYSTEM_UI_CHANGING_LAYOUT = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_FULLSCREEN; + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.STATUS_BAR_TRANSLUCENT + | View.NAVIGATION_BAR_TRANSLUCENT; /** * Keyguard stuff @@ -293,6 +295,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mOrientationSensorEnabled = false; int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; boolean mHasSoftInput = false; + boolean mTouchExplorationEnabled = false; int mPointerLocationMode = 0; // guarded by mLock @@ -1073,14 +1076,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHasNavigationBar = true; } - if (mHasNavigationBar) { - // The navigation bar is at the right in landscape; it seems always - // useful to hide it for showing a video. - mCanHideNavigationBar = true; - } else { - mCanHideNavigationBar = false; - } - // For demo purposes, allow the rotation of the HDMI display to be controlled. // By default, HDMI locks rotation to landscape. if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { @@ -1100,6 +1095,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { !"true".equals(SystemProperties.get("config.override_forced_orient")); } + /** + * @return whether the navigation bar can be hidden, e.g. the device has a + * navigation bar and touch exploration is not enabled + */ + private boolean canHideNavigationBar() { + return mHasNavigationBar && !mTouchExplorationEnabled; + } + @Override public boolean isDefaultOrientationForced() { return mForceDefaultOrientation; @@ -2580,7 +2583,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { int availRight, availBottom; - if (mCanHideNavigationBar && + if (canHideNavigationBar() && (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; @@ -2697,6 +2700,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean navTranslucent = (sysui & View.NAVIGATION_BAR_TRANSLUCENT) != 0; boolean transientAllowed = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; navTranslucent &= !transientAllowed; // transient trumps translucent + navTranslucent &= isTranslucentNavigationAllowed(); // When the navigation bar isn't visible, we put up a fake // input window to catch all touch events. This way we can @@ -2717,7 +2721,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // For purposes of positioning and showing the nav bar, if we have // decided that it can't be hidden (because of the screen aspect ratio), // then take that into account. - navVisible |= !mCanHideNavigationBar; + navVisible |= !canHideNavigationBar(); boolean updateSysUiVisibility = false; if (mNavigationBar != null) { @@ -2987,8 +2991,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; pf.top = df.top = of.top = cf.top = vf.top = mDockTop; pf.right = df.right = of.right = cf.right = vf.right = mDockRight; - // IM dock windows always go above the nav bar. - pf.bottom = df.bottom = of.bottom = cf.bottom = vf.bottom = mStableBottom; + // IM dock windows layout below the nav bar... + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; + // ...with content insets above the nav bar + cf.bottom = vf.bottom = mStableBottom; // IM dock windows always go to the bottom of the screen. attrs.gravity = Gravity.BOTTOM; mDockLayer = win.getSurfaceLayer(); @@ -3001,9 +3007,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { dcf.bottom = mSystemBottom; final boolean inheritTranslucentDecor = (attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; - if (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW - && attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW - && !inheritTranslucentDecor) { + final boolean isAppWindow = + attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && + attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + final boolean topAtRest = + win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); + if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0) { @@ -3063,7 +3072,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; pf.bottom = df.bottom = of.bottom = mOverscanScreenTop + mOverscanScreenHeight; - } else if (mCanHideNavigationBar + } else if (canHideNavigationBar() && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { @@ -3201,7 +3210,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { = mOverscanScreenLeft + mOverscanScreenWidth; pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop + mOverscanScreenHeight; - } else if (mCanHideNavigationBar + } else if (canHideNavigationBar() && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 && (attrs.type == TYPE_TOAST || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW @@ -4275,12 +4284,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { })) { return; } + Slog.i(TAG, "No lock screen! waitForWindowDrawn false"); + } catch (RemoteException ex) { // Can't happen in system process. } } - Slog.i(TAG, "No lock screen!"); + Slog.i(TAG, "No lock screen! windowToken=" + windowToken); finishScreenTurningOn(screenOnListener); } @@ -5088,6 +5099,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { vis = (vis & ~flags) | (oldVis & flags); } + if (!isTranslucentNavigationAllowed()) { + vis &= ~View.NAVIGATION_BAR_TRANSLUCENT; + } + // update status bar boolean transientAllowed = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; @@ -5138,6 +5153,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { && (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; } + /** + * @return whether the navigation bar can be made translucent, e.g. touch + * exploration is not enabled + */ + private boolean isTranslucentNavigationAllowed() { + return !mTouchExplorationEnabled; + } + // Use this instead of checking config_showNavigationBar so that it can be consistently // overridden by qemu.hw.mainkeys in the emulator. @Override @@ -5181,6 +5204,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public void setTouchExplorationEnabled(boolean enabled) { + mTouchExplorationEnabled = enabled; + } + + @Override public boolean isTopLevelWindow(int windowType) { if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { diff --git a/preloaded-classes b/preloaded-classes index cb2ace388398..d161bc162f72 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -76,7 +76,6 @@ android.app.ActivityThread$ProviderClientRecord android.app.ActivityThread$ProviderKey android.app.ActivityThread$ProviderRefCount android.app.ActivityThread$ReceiverData -android.app.ActivityThread$ResourcesKey android.app.ActivityThread$ResultData android.app.ActivityThread$ServiceArgsData android.app.ActivityThread$StopInfo @@ -796,7 +795,6 @@ android.os.storage.StorageVolume$1 android.preference.CheckBoxPreference android.preference.GenericInflater android.preference.GenericInflater$Parent -android.preference.OnDependencyChangeListener android.preference.Preference android.preference.Preference$OnPreferenceChangeInternalListener android.preference.Preference$OnPreferenceChangeListener @@ -971,7 +969,6 @@ android.view.Choreographer$CallbackRecord android.view.Choreographer$FrameDisplayEventReceiver android.view.Choreographer$FrameHandler android.view.CollapsibleActionView -android.view.CompatibilityInfoHolder android.view.ContextMenu android.view.ContextMenu$ContextMenuInfo android.view.ContextThemeWrapper @@ -1313,10 +1310,8 @@ android.widget.EdgeEffect android.widget.EditText android.widget.Editor android.widget.Editor$Blink -android.widget.Editor$EasyEditSpanController android.widget.Editor$InputContentType android.widget.Editor$InputMethodState -android.widget.Editor$UserDictionaryListener android.widget.ExpandableListView android.widget.Filter android.widget.Filter$FilterListener @@ -1946,7 +1941,6 @@ java.lang.UnsafeByteSequence java.lang.UnsatisfiedLinkError java.lang.UnsupportedOperationException java.lang.VMClassLoader -java.lang.VMThread java.lang.VerifyError java.lang.VirtualMachineError java.lang.Void @@ -2310,7 +2304,6 @@ java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock java.util.jar.Attributes java.util.jar.Attributes$Name -java.util.jar.InitManifest java.util.jar.JarEntry java.util.jar.JarFile java.util.jar.JarFile$1JarFileEnumerator diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index d2d528020822..546324a73e05 100644 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -766,13 +766,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - mStateChangeCallbacks.register(callback); + if (callback != null) { + mStateChangeCallbacks.register(callback); + } break; } case MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; - mStateChangeCallbacks.unregister(callback); + if (callback != null) { + mStateChangeCallbacks.unregister(callback); + } break; } case MESSAGE_BLUETOOTH_SERVICE_CONNECTED: diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 59b559e0de87..70418e8d04bf 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -353,6 +353,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { */ private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15; + /** + * PAC manager has received new port. + */ + private static final int EVENT_PROXY_HAS_CHANGED = 16; + /** Handler used for internal events. */ private InternalHandler mHandler; /** Handler used for incoming {@link NetworkStateTracker} events. */ @@ -679,7 +684,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { }, new IntentFilter(filter)); - mPacManager = new PacManager(mContext); + mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED); filter = new IntentFilter(); filter.addAction(CONNECTED_TO_PROVISIONING_NETWORK_ACTION); @@ -3124,6 +3129,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { handleNetworkSamplingTimeout(); break; } + case EVENT_PROXY_HAS_CHANGED: { + handleApplyDefaultProxy((ProxyProperties)msg.obj); + break; + } } } } @@ -4247,6 +4256,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { addrTried ++) { // Choose the address at random but make sure its type is supported + // TODO: This doesn't work 100% of the time, because we may end up + // trying the same invalid address more than once and ignoring one + // of the valid addresses. InetAddress hostAddr = addresses[rand.nextInt(addresses.length)]; if (((hostAddr instanceof Inet4Address) && linkHasIpv4) || ((hostAddr instanceof Inet6Address) && linkHasIpv6)) { @@ -4271,10 +4283,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { } // Rewrite the url to have numeric address to use the specific route. - // I also set the "Connection" to "Close" as by default "Keep-Alive" - // is used which is useless in this case. - URL newUrl = new URL(orgUri.getScheme() + "://" - + hostAddr.getHostAddress() + orgUri.getPath()); + URL newUrl = new URL(orgUri.getScheme(), + hostAddr.getHostAddress(), orgUri.getPath()); log("isMobileOk: newUrl=" + newUrl); HttpURLConnection urlConn = null; @@ -4287,6 +4297,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { urlConn.setReadTimeout(SOCKET_TIMEOUT_MS); urlConn.setUseCaches(false); urlConn.setAllowUserInteraction(false); + // Set the "Connection" to "Close" as by default "Keep-Alive" + // is used which is useless in this case. urlConn.setRequestProperty("Connection", "close"); int responseCode = urlConn.getResponseCode(); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 59ec7777c6c9..c7ca1ea9cb3f 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -1227,6 +1227,9 @@ class MountService extends IMountService.Stub descriptionId, primary, removable, emulated, mtpReserve, allowMassStorage, maxFileSize, null); addVolumeLocked(volume); + + // Until we hear otherwise, treat as unmounted + mVolumeStates.put(volume.getPath(), Environment.MEDIA_UNMOUNTED); } } @@ -2781,6 +2784,7 @@ class MountService extends IMountService.Stub final StorageVolume v = mVolumes.get(i); pw.print(" "); pw.println(v.toString()); + pw.println(" state=" + mVolumeStates.get(v.getPath())); } } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index b881934879d6..7431f1d0af43 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -1167,11 +1167,19 @@ public class NotificationManagerService extends INotificationManager.Stub } if (packageChanged) { // We cancel notifications for packages which have just been disabled - final int enabled = mContext.getPackageManager() - .getApplicationEnabledSetting(pkgName); - if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED - || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { - cancelNotifications = false; + try { + final int enabled = mContext.getPackageManager() + .getApplicationEnabledSetting(pkgName); + if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED + || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { + cancelNotifications = false; + } + } catch (IllegalArgumentException e) { + // Package doesn't exist; probably racing with uninstall. + // cancelNotifications is already true, so nothing to do here. + if (DBG) { + Slog.i(TAG, "Exception trying to look up app enabled setting", e); + } } } pkgList = new String[]{pkgName}; diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index 83e69d6f355a..ccac0d32ea7b 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1419,6 +1419,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { Settings.Secure.TOUCH_EXPLORATION_ENABLED, enabled ? 1 : 0, userState.mUserId); } + try { + mWindowManagerService.setTouchExplorationEnabled(enabled); + } catch (RemoteException e) { + e.printStackTrace(); + } } private boolean canRequestAndRequestsTouchExplorationLocked(Service service) { diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java index 1b8876d745c0..a99b58a256e6 100644 --- a/services/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/java/com/android/server/accessibility/TouchExplorer.java @@ -736,9 +736,9 @@ class TouchExplorer implements EventStreamTransformation { + "there is at least one pointer down!"); } case MotionEvent.ACTION_UP: { + mAms.onTouchInteractionEnd(); // Announce the end of a the touch interaction. sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); - mAms.onTouchInteractionEnd(); mLongPressingPointerId = -1; mLongPressingPointerDeltaX = 0; mLongPressingPointerDeltaY = 0; @@ -822,6 +822,7 @@ class TouchExplorer implements EventStreamTransformation { AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext); if (accessibilityManager.isEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain(type); + event.setWindowId(mAms.getActiveWindowId()); accessibilityManager.sendAccessibilityEvent(event); switch (type) { case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: { diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index dd9ae4c9397e..cc43a9cce6ef 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -293,17 +293,16 @@ public class AccountManagerService return mUserManager; } - private UserAccounts initUser(int userId) { - synchronized (mUsers) { - UserAccounts accounts = mUsers.get(userId); - if (accounts == null) { - accounts = new UserAccounts(mContext, userId); - mUsers.append(userId, accounts); - purgeOldGrants(accounts); - validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */); - } - return accounts; + /* Caller should lock mUsers */ + private UserAccounts initUserLocked(int userId) { + UserAccounts accounts = mUsers.get(userId); + if (accounts == null) { + accounts = new UserAccounts(mContext, userId); + mUsers.append(userId, accounts); + purgeOldGrants(accounts); + validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */); } + return accounts; } private void purgeOldGrantsAll() { @@ -427,7 +426,7 @@ public class AccountManagerService synchronized (mUsers) { UserAccounts accounts = mUsers.get(userId); if (accounts == null) { - accounts = initUser(userId); + accounts = initUserLocked(userId); mUsers.append(userId, accounts); } return accounts; @@ -1798,16 +1797,14 @@ public class AccountManagerService private AccountAndUser[] getAccounts(int[] userIds) { final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList(); - synchronized (mUsers) { - for (int userId : userIds) { - UserAccounts userAccounts = getUserAccounts(userId); - if (userAccounts == null) continue; - synchronized (userAccounts.cacheLock) { - Account[] accounts = getAccountsFromCacheLocked(userAccounts, null, - Binder.getCallingUid(), null); - for (int a = 0; a < accounts.length; a++) { - runningAccounts.add(new AccountAndUser(accounts[a], userId)); - } + for (int userId : userIds) { + UserAccounts userAccounts = getUserAccounts(userId); + if (userAccounts == null) continue; + synchronized (userAccounts.cacheLock) { + Account[] accounts = getAccountsFromCacheLocked(userAccounts, null, + Binder.getCallingUid(), null); + for (int a = 0; a < accounts.length; a++) { + runningAccounts.add(new AccountAndUser(accounts[a], userId)); } } } @@ -2858,7 +2855,8 @@ public class AccountManagerService || callingUid == Process.myUid()) { return unfiltered; } - if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) { + UserInfo user = mUserManager.getUserInfo(userAccounts.userId); + if (user != null && user.isRestricted()) { String[] packages = mPackageManager.getPackagesForUid(callingUid); // If any of the packages is a white listed package, return the full set, // otherwise return non-shared accounts only. diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 27ca7a05d9c4..b69a0c8185b6 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import android.os.Handler; +import android.os.Looper; import android.util.ArrayMap; import com.android.internal.app.ProcessStats; import com.android.internal.os.BatteryStatsImpl; @@ -166,7 +167,8 @@ public final class ActiveServices { static final int MSG_BG_START_TIMEOUT = 1; - ServiceMap(int userId) { + ServiceMap(Looper looper, int userId) { + super(looper); mUserId = userId; } @@ -255,7 +257,7 @@ public final class ActiveServices { private ServiceMap getServiceMap(int callingUser) { ServiceMap smap = mServiceMap.get(callingUser); if (smap == null) { - smap = new ServiceMap(callingUser); + smap = new ServiceMap(mAm.mHandler.getLooper(), callingUser); mServiceMap.put(callingUser, smap); } return smap; @@ -2417,7 +2419,11 @@ public final class ActiveServices { int[] users = mAm.getUsersLocked(); if ("all".equals(name)) { for (int user : users) { - ArrayMap<ComponentName, ServiceRecord> alls = getServices(user); + ServiceMap smap = mServiceMap.get(user); + if (smap == null) { + continue; + } + ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName; for (int i=0; i<alls.size(); i++) { ServiceRecord r1 = alls.valueAt(i); services.add(r1); @@ -2438,7 +2444,11 @@ public final class ActiveServices { } for (int user : users) { - ArrayMap<ComponentName, ServiceRecord> alls = getServices(user); + ServiceMap smap = mServiceMap.get(user); + if (smap == null) { + continue; + } + ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName; for (int i=0; i<alls.size(); i++) { ServiceRecord r1 = alls.valueAt(i); if (componentName != null) { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index fe91b6c52331..4fbbb785cff1 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -226,7 +226,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final boolean DEBUG_RESULTS = localLOGV || false; static final boolean DEBUG_SERVICE = localLOGV || false; static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false; - static final boolean DEBUG_STACK = localLOGV || false; + static final boolean DEBUG_STACK = localLOGV || true; static final boolean DEBUG_SWITCH = localLOGV || false; static final boolean DEBUG_TASKS = localLOGV || false; static final boolean DEBUG_THUMBNAILS = localLOGV || false; @@ -6489,26 +6489,53 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions() { + public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions( + String packageName, boolean incoming) { enforceNotIsolatedCaller("getPersistedUriPermissions"); + Preconditions.checkNotNull(packageName, "packageName"); + final int callingUid = Binder.getCallingUid(); + final IPackageManager pm = AppGlobals.getPackageManager(); + try { + final int packageUid = pm.getPackageUid(packageName, UserHandle.getUserId(callingUid)); + if (packageUid != callingUid) { + throw new SecurityException( + "Package " + packageName + " does not belong to calling UID " + callingUid); + } + } catch (RemoteException e) { + throw new SecurityException("Failed to verify package name ownership"); + } + + final ArrayList<android.content.UriPermission> result = Lists.newArrayList(); synchronized (this) { - final int callingUid = Binder.getCallingUid(); - final ArrayList<android.content.UriPermission> result = Lists.newArrayList(); - final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); - if (perms == null) { - Slog.w(TAG, "No permission grants found for UID " + callingUid); + if (incoming) { + final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); + if (perms == null) { + Slog.w(TAG, "No permission grants found for " + packageName); + } else { + final int size = perms.size(); + for (int i = 0; i < size; i++) { + final UriPermission perm = perms.valueAt(i); + if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) { + result.add(perm.buildPersistedPublicApiObject()); + } + } + } } else { - final int size = perms.size(); + final int size = mGrantedUriPermissions.size(); for (int i = 0; i < size; i++) { - final UriPermission perm = perms.valueAt(i); - if (perm.persistedModeFlags != 0) { - result.add(perm.buildPersistedPublicApiObject()); + final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i); + final int permsSize = perms.size(); + for (int j = 0; j < permsSize; j++) { + final UriPermission perm = perms.valueAt(j); + if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) { + result.add(perm.buildPersistedPublicApiObject()); + } } } } - return new ParceledListSlice<android.content.UriPermission>(result); } + return new ParceledListSlice<android.content.UriPermission>(result); } @Override @@ -6755,7 +6782,6 @@ public final class ActivityManagerService extends ActivityManagerNative private void cleanUpRemovedTaskLocked(TaskRecord tr, int flags) { tr.disposeThumbnail(); mRecentTasks.remove(tr); - mStackSupervisor.removeTask(tr); final boolean killProcesses = (flags&ActivityManager.REMOVE_TASK_KILL_PROCESS) != 0; Intent baseIntent = new Intent( tr.intent != null ? tr.intent : tr.affinityIntent); @@ -7526,16 +7552,30 @@ public final class ActivityManagerService extends ActivityManagerNative + cpr.appInfo.packageName + ": " + e); } - ProcessRecord proc = startProcessLocked(cpi.processName, - cpr.appInfo, false, 0, "content provider", - new ComponentName(cpi.applicationInfo.packageName, - cpi.name), false, false, false); - if (proc == null) { - Slog.w(TAG, "Unable to launch app " - + cpi.applicationInfo.packageName + "/" - + cpi.applicationInfo.uid + " for provider " - + name + ": process is bad"); - return null; + // Use existing process if already started + ProcessRecord proc = getProcessRecordLocked( + cpi.processName, cpr.appInfo.uid, false); + if (proc != null && proc.thread != null) { + if (DEBUG_PROVIDER) { + Slog.d(TAG, "Installing in existing process " + proc); + } + proc.pubProviders.put(cpi.name, cpr); + try { + proc.thread.scheduleInstallProvider(cpi); + } catch (RemoteException e) { + } + } else { + proc = startProcessLocked(cpi.processName, + cpr.appInfo, false, 0, "content provider", + new ComponentName(cpi.applicationInfo.packageName, + cpi.name), false, false, false); + if (proc == null) { + Slog.w(TAG, "Unable to launch app " + + cpi.applicationInfo.packageName + "/" + + cpi.applicationInfo.uid + " for provider " + + name + ": process is bad"); + return null; + } } cpr.launchingApp = proc; mLaunchingProviders.add(cpr); @@ -14227,6 +14267,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } + boolean mayBeTop = false; + for (int is = app.services.size()-1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE @@ -14387,18 +14429,27 @@ public final class ActivityManagerService extends ActivityManagerNative if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) { schedGroup = Process.THREAD_GROUP_DEFAULT; } - if (clientProcState <= - ActivityManager.PROCESS_STATE_PERSISTENT_UI && - clientProcState >= - ActivityManager.PROCESS_STATE_PERSISTENT) { - // Persistent processes don't allow us to become top. - // However the top process DOES allow us to become top, - // because in that case we are running because the current - // top process wants us, so we should be counted as part - // of the top set and not just running for some random - // unknown reason in the background. - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { + if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { + // Special handling of clients who are in the top state. + // We *may* want to consider this process to be in the + // top state as well, but only if there is not another + // reason for it to be running. Being on the top is a + // special state, meaning you are specifically running + // for the current top app. If the process is already + // running in the background for some other reason, it + // is more important to continue considering it to be + // in the background state. + mayBeTop = true; + clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + } else { + // Special handling for above-top states (persistent + // processes). These should not bring the current process + // into the top state, since they are not on top. Instead + // give them the best state after that. + clientProcState = + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } } } else { if (clientProcState < @@ -14486,18 +14537,27 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjSourceOom = clientAdj; app.adjTarget = cpr.name; } - if (clientProcState <= - ActivityManager.PROCESS_STATE_PERSISTENT_UI && - clientProcState >= - ActivityManager.PROCESS_STATE_PERSISTENT) { - // Persistent processes don't allow us to become top. - // However the top process DOES allow us to become top, - // because in that case we are running because the current - // top process wants us, so we should be counted as part - // of the top set and not just running for some random - // unknown reason in the background. - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { + if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { + // Special handling of clients who are in the top state. + // We *may* want to consider this process to be in the + // top state as well, but only if there is not another + // reason for it to be running. Being on the top is a + // special state, meaning you are specifically running + // for the current top app. If the process is already + // running in the background for some other reason, it + // is more important to continue considering it to be + // in the background state. + mayBeTop = true; + clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + } else { + // Special handling for above-top states (persistent + // processes). These should not bring the current process + // into the top state, since they are not on top. Instead + // give them the best state after that. + clientProcState = + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } } if (procState > clientProcState) { procState = clientProcState; @@ -14524,6 +14584,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { + // A client of one of our services or providers is in the top state. We + // *may* want to be in the top state, but not if we are already running in + // the background for some other reason. For the decision here, we are going + // to pick out a few specific states that we want to remain in when a client + // is top (states that tend to be longer-term) and otherwise allow it to go + // to the top state. + switch (procState) { + case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: + case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: + case ActivityManager.PROCESS_STATE_SERVICE: + // These all are longer-term states, so pull them up to the top + // of the background states, but not all the way to the top state. + procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + break; + default: + // Otherwise, top is a better choice, so take it. + procState = ActivityManager.PROCESS_STATE_TOP; + break; + } + } + if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3); diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java index dbc05fa4288b..50a7b5c5e56c 100644 --- a/services/java/com/android/server/am/ProcessStatsService.java +++ b/services/java/com/android/server/am/ProcessStatsService.java @@ -473,11 +473,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { current.setDataPosition(0); ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current); current.recycle(); - int i = 0; - while (i < files.size() && (stats.mTimePeriodEndRealtime + int i = files.size()-1; + while (i >= 0 && (stats.mTimePeriodEndRealtime - stats.mTimePeriodStartRealtime) < minTime) { AtomicFile file = new AtomicFile(new File(files.get(i))); - i++; + i--; ProcessStats moreStats = new ProcessStats(false); readLocked(moreStats, file); if (moreStats.mReadError == null) { @@ -490,7 +490,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { - moreStats.mTimePeriodStartRealtime, sb); Slog.i(TAG, sb.toString()); } else { - Slog.w(TAG, "Failure reading " + files.get(i-1) + "; " + Slog.w(TAG, "Failure reading " + files.get(i+1) + "; " + moreStats.mReadError); continue; } @@ -566,6 +566,15 @@ public final class ProcessStatsService extends IProcessStats.Stub { return; } + long ident = Binder.clearCallingIdentity(); + try { + dumpInner(fd, pw, args); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void dumpInner(FileDescriptor fd, PrintWriter pw, String[] args) { final long now = SystemClock.uptimeMillis(); boolean isCheckin = false; diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index 5868c08afae9..684f247f63f7 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -20,7 +20,6 @@ import android.content.Intent; import android.net.Uri; import android.os.UserHandle; import android.util.Log; -import android.util.Slog; import com.android.internal.util.Preconditions; import com.google.android.collect.Sets; diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java index 1cb2fe384132..837fb05cc923 100644 --- a/services/java/com/android/server/connectivity/PacManager.java +++ b/services/java/com/android/server/connectivity/PacManager.java @@ -27,6 +27,7 @@ import android.content.ServiceConnection; import android.net.Proxy; import android.net.ProxyProperties; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -89,6 +90,9 @@ public class PacManager { private boolean mHasSentBroadcast; private boolean mHasDownloaded; + private Handler mConnectivityHandler; + private int mProxyMessage; + /** * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac. */ @@ -128,7 +132,7 @@ public class PacManager { } } - public PacManager(Context context) { + public PacManager(Context context, Handler handler, int proxyMessage) { mContext = context; mLastPort = -1; @@ -136,6 +140,8 @@ public class PacManager { context, 0, new Intent(ACTION_PAC_REFRESH), 0); context.registerReceiver(new PacRefreshIntentReceiver(), new IntentFilter(ACTION_PAC_REFRESH)); + mConnectivityHandler = handler; + mProxyMessage = proxyMessage; } private AlarmManager getAlarmManager() { @@ -156,6 +162,10 @@ public class PacManager { */ public synchronized boolean setCurrentProxyScriptUrl(ProxyProperties proxy) { if (!TextUtils.isEmpty(proxy.getPacFileUrl())) { + if (proxy.getPacFileUrl().equals(mPacUrl)) { + // Allow to send broadcast, nothing to do. + return false; + } synchronized (mProxyLock) { mPacUrl = proxy.getPacFileUrl(); } @@ -356,16 +366,7 @@ public class PacManager { } private void sendPacBroadcast(ProxyProperties proxy) { - Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | - Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy); - final long ident = Binder.clearCallingIdentity(); - try { - mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); - } finally { - Binder.restoreCallingIdentity(ident); - } + mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy)); } private synchronized void sendProxyIfNeeded() { diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index e84f90ec4b5c..fb6e9edcbb6c 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -383,13 +383,12 @@ public class PackageManagerService extends IPackageManager.Stub { // All available services, for your resolving pleasure. final ServiceIntentResolver mServices = new ServiceIntentResolver(); - // Keys are String (provider class name), values are Provider. - final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent = - new HashMap<ComponentName, PackageParser.Provider>(); + // All available providers, for your resolving pleasure. + final ProviderIntentResolver mProviders = new ProviderIntentResolver(); // Mapping from provider base names (first directory in content URI codePath) // to the provider information. - final HashMap<String, PackageParser.Provider> mProviders = + final HashMap<String, PackageParser.Provider> mProvidersByAuthority = new HashMap<String, PackageParser.Provider>(); // Mapping from instrumentation class names to info about them. @@ -2095,7 +2094,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (!sUserManager.exists(userId)) return null; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info"); synchronized (mPackages) { - PackageParser.Provider p = mProvidersByComponent.get(component); + PackageParser.Provider p = mProviders.mProviders.get(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getProviderInfo " + component + ": " + p); if (p != null && mSettings.isEnabledLPr(p.info, flags, userId)) { @@ -3121,6 +3120,43 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public List<ResolveInfo> queryIntentContentProviders( + Intent intent, String resolvedType, int flags, int userId) { + if (!sUserManager.exists(userId)) return Collections.emptyList(); + ComponentName comp = intent.getComponent(); + if (comp == null) { + if (intent.getSelector() != null) { + intent = intent.getSelector(); + comp = intent.getComponent(); + } + } + if (comp != null) { + final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); + final ProviderInfo pi = getProviderInfo(comp, flags, userId); + if (pi != null) { + final ResolveInfo ri = new ResolveInfo(); + ri.providerInfo = pi; + list.add(ri); + } + return list; + } + + // reader + synchronized (mPackages) { + String pkgName = intent.getPackage(); + if (pkgName == null) { + return mProviders.queryIntent(intent, resolvedType, flags, userId); + } + final PackageParser.Package pkg = mPackages.get(pkgName); + if (pkg != null) { + return mProviders.queryIntentForPackage( + intent, resolvedType, flags, pkg.providers, userId); + } + return null; + } + } + + @Override public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) { final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; @@ -3293,7 +3329,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (!sUserManager.exists(userId)) return null; // reader synchronized (mPackages) { - final PackageParser.Provider provider = mProviders.get(name); + final PackageParser.Provider provider = mProvidersByAuthority.get(name); PackageSetting ps = provider != null ? mSettings.mPackages.get(provider.owner.packageName) : null; @@ -3314,8 +3350,8 @@ public class PackageManagerService extends IPackageManager.Stub { public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) { // reader synchronized (mPackages) { - final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProviders.entrySet() - .iterator(); + final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority + .entrySet().iterator(); final int userId = UserHandle.getCallingUserId(); while (i.hasNext()) { Map.Entry<String, PackageParser.Provider> entry = i.next(); @@ -3341,7 +3377,7 @@ public class PackageManagerService extends IPackageManager.Stub { ArrayList<ProviderInfo> finalList = null; // reader synchronized (mPackages) { - final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator(); + final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator(); final int userId = processName != null ? UserHandle.getUserId(uid) : UserHandle.getCallingUserId(); while (i.hasNext()) { @@ -4313,8 +4349,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (p.info.authority != null) { String names[] = p.info.authority.split(";"); for (int j = 0; j < names.length; j++) { - if (mProviders.containsKey(names[j])) { - PackageParser.Provider other = mProviders.get(names[j]); + if (mProvidersByAuthority.containsKey(names[j])) { + PackageParser.Provider other = mProvidersByAuthority.get(names[j]); Slog.w(TAG, "Can't install because provider name " + names[j] + " (in package " + pkg.applicationInfo.packageName + ") is already used by " @@ -4745,8 +4781,7 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.Provider p = pkg.providers.get(i); p.info.processName = fixProcessName(pkg.applicationInfo.processName, p.info.processName, pkg.applicationInfo.uid); - mProvidersByComponent.put(new ComponentName(p.info.packageName, - p.info.name), p); + mProviders.addProvider(p); p.syncable = p.info.isSyncable; if (p.info.authority != null) { String names[] = p.info.authority.split(";"); @@ -4763,8 +4798,8 @@ public class PackageManagerService extends IPackageManager.Stub { p = new PackageParser.Provider(p); p.syncable = false; } - if (!mProviders.containsKey(names[j])) { - mProviders.put(names[j], p); + if (!mProvidersByAuthority.containsKey(names[j])) { + mProvidersByAuthority.put(names[j], p); if (p.info.authority == null) { p.info.authority = names[j]; } else { @@ -4777,7 +4812,7 @@ public class PackageManagerService extends IPackageManager.Stub { + p.info.isSyncable); } } else { - PackageParser.Provider other = mProviders.get(names[j]); + PackageParser.Provider other = mProvidersByAuthority.get(names[j]); Slog.w(TAG, "Skipping provider name " + names[j] + " (in package " + pkg.applicationInfo.packageName + "): name already used by " @@ -5108,8 +5143,7 @@ public class PackageManagerService extends IPackageManager.Stub { int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); - mProvidersByComponent.remove(new ComponentName(p.info.packageName, - p.info.name)); + mProviders.removeProvider(p); if (p.info.authority == null) { /* There was another ContentProvider with this authority when @@ -5120,8 +5154,8 @@ public class PackageManagerService extends IPackageManager.Stub { } String names[] = p.info.authority.split(";"); for (int j = 0; j < names.length; j++) { - if (mProviders.get(names[j]) == p) { - mProviders.remove(names[j]); + if (mProvidersByAuthority.get(names[j]) == p) { + mProvidersByAuthority.remove(names[j]); if (DEBUG_REMOVE) { if (chatty) Log.d(TAG, "Unregistered content provider: " + names[j] @@ -5962,6 +5996,195 @@ public class PackageManagerService extends IPackageManager.Stub { private int mFlags; }; + private final class ProviderIntentResolver + extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> { + public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, + boolean defaultOnly, int userId) { + mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0; + return super.queryIntent(intent, resolvedType, defaultOnly, userId); + } + + public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, + int userId) { + if (!sUserManager.exists(userId)) + return null; + mFlags = flags; + return super.queryIntent(intent, resolvedType, + (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId); + } + + public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, + int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) { + if (!sUserManager.exists(userId)) + return null; + if (packageProviders == null) { + return null; + } + mFlags = flags; + final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; + final int N = packageProviders.size(); + ArrayList<PackageParser.ProviderIntentInfo[]> listCut = + new ArrayList<PackageParser.ProviderIntentInfo[]>(N); + + ArrayList<PackageParser.ProviderIntentInfo> intentFilters; + for (int i = 0; i < N; ++i) { + intentFilters = packageProviders.get(i).intents; + if (intentFilters != null && intentFilters.size() > 0) { + PackageParser.ProviderIntentInfo[] array = + new PackageParser.ProviderIntentInfo[intentFilters.size()]; + intentFilters.toArray(array); + listCut.add(array); + } + } + return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); + } + + public final void addProvider(PackageParser.Provider p) { + mProviders.put(p.getComponentName(), p); + if (DEBUG_SHOW_INFO) { + Log.v(TAG, " " + + (p.info.nonLocalizedLabel != null + ? p.info.nonLocalizedLabel : p.info.name) + ":"); + Log.v(TAG, " Class=" + p.info.name); + } + final int NI = p.intents.size(); + int j; + for (j = 0; j < NI; j++) { + PackageParser.ProviderIntentInfo intent = p.intents.get(j); + if (DEBUG_SHOW_INFO) { + Log.v(TAG, " IntentFilter:"); + intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); + } + if (!intent.debugCheck()) { + Log.w(TAG, "==> For Provider " + p.info.name); + } + addFilter(intent); + } + } + + public final void removeProvider(PackageParser.Provider p) { + mProviders.remove(p.getComponentName()); + if (DEBUG_SHOW_INFO) { + Log.v(TAG, " " + (p.info.nonLocalizedLabel != null + ? p.info.nonLocalizedLabel : p.info.name) + ":"); + Log.v(TAG, " Class=" + p.info.name); + } + final int NI = p.intents.size(); + int j; + for (j = 0; j < NI; j++) { + PackageParser.ProviderIntentInfo intent = p.intents.get(j); + if (DEBUG_SHOW_INFO) { + Log.v(TAG, " IntentFilter:"); + intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); + } + removeFilter(intent); + } + } + + @Override + protected boolean allowFilterResult( + PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) { + ProviderInfo filterPi = filter.provider.info; + for (int i = dest.size() - 1; i >= 0; i--) { + ProviderInfo destPi = dest.get(i).providerInfo; + if (destPi.name == filterPi.name + && destPi.packageName == filterPi.packageName) { + return false; + } + } + return true; + } + + @Override + protected PackageParser.ProviderIntentInfo[] newArray(int size) { + return new PackageParser.ProviderIntentInfo[size]; + } + + @Override + protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) { + if (!sUserManager.exists(userId)) + return true; + PackageParser.Package p = filter.provider.owner; + if (p != null) { + PackageSetting ps = (PackageSetting) p.mExtras; + if (ps != null) { + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 + && ps.getStopped(userId); + } + } + return false; + } + + @Override + protected boolean isPackageForFilter(String packageName, + PackageParser.ProviderIntentInfo info) { + return packageName.equals(info.provider.owner.packageName); + } + + @Override + protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter, + int match, int userId) { + if (!sUserManager.exists(userId)) + return null; + final PackageParser.ProviderIntentInfo info = filter; + if (!mSettings.isEnabledLPr(info.provider.info, mFlags, userId)) { + return null; + } + final PackageParser.Provider provider = info.provider; + if (mSafeMode && (provider.info.applicationInfo.flags + & ApplicationInfo.FLAG_SYSTEM) == 0) { + return null; + } + PackageSetting ps = (PackageSetting) provider.owner.mExtras; + if (ps == null) { + return null; + } + ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags, + ps.readUserState(userId), userId); + if (pi == null) { + return null; + } + final ResolveInfo res = new ResolveInfo(); + res.providerInfo = pi; + if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { + res.filter = filter; + } + res.priority = info.getPriority(); + res.preferredOrder = provider.owner.mPreferredOrder; + res.match = match; + res.isDefault = info.hasDefault; + res.labelRes = info.labelRes; + res.nonLocalizedLabel = info.nonLocalizedLabel; + res.icon = info.icon; + res.system = isSystemApp(res.providerInfo.applicationInfo); + return res; + } + + @Override + protected void sortResults(List<ResolveInfo> results) { + Collections.sort(results, mResolvePrioritySorter); + } + + @Override + protected void dumpFilter(PrintWriter out, String prefix, + PackageParser.ProviderIntentInfo filter) { + out.print(prefix); + out.print( + Integer.toHexString(System.identityHashCode(filter.provider))); + out.print(' '); + filter.provider.printComponentShortName(out); + out.print(" filter "); + out.println(Integer.toHexString(System.identityHashCode(filter))); + } + + private final HashMap<ComponentName, PackageParser.Provider> mProviders + = new HashMap<ComponentName, PackageParser.Provider>(); + private int mFlags; + }; + private static final Comparator<ResolveInfo> mResolvePrioritySorter = new Comparator<ResolveInfo>() { public int compare(ResolveInfo r1, ResolveInfo r2) { @@ -10454,6 +10677,11 @@ public class PackageManagerService extends IPackageManager.Stub { dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { dumpState.setTitlePrinted(true); } + if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:" + : "Provider Resolver Table:", " ", packageName, + dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS))) { + dumpState.setTitlePrinted(true); + } } if (dumpState.isDumping(DumpState.DUMP_PREFERRED)) { @@ -10498,7 +10726,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dumpState.isDumping(DumpState.DUMP_PROVIDERS)) { boolean printedSomething = false; - for (PackageParser.Provider p : mProvidersByComponent.values()) { + for (PackageParser.Provider p : mProviders.mProviders.values()) { if (packageName != null && !packageName.equals(p.info.packageName)) { continue; } @@ -10512,7 +10740,8 @@ public class PackageManagerService extends IPackageManager.Stub { pw.print(" "); pw.println(p.toString()); } printedSomething = false; - for (Map.Entry<String, PackageParser.Provider> entry : mProviders.entrySet()) { + for (Map.Entry<String, PackageParser.Provider> entry : + mProvidersByAuthority.entrySet()) { PackageParser.Provider p = entry.getValue(); if (packageName != null && !packageName.equals(p.info.packageName)) { continue; diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java index 798cea36caaf..4866f5792c38 100644 --- a/services/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/java/com/android/server/print/RemotePrintSpooler.java @@ -255,6 +255,31 @@ final class RemotePrintSpooler { return false; } + public final void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) { + throwIfCalledOnMainThread(); + synchronized (mLock) { + throwIfDestroyedLocked(); + mCanUnbind = false; + } + try { + getRemoteInstanceLazy().setPrintJobCancelling(printJobId, + cancelling); + } catch (RemoteException re) { + Slog.e(LOG_TAG, "Error setting print job cancelling.", re); + } catch (TimeoutException te) { + Slog.e(LOG_TAG, "Error setting print job cancelling.", te); + } finally { + if (DEBUG) { + Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + + "] setPrintJobCancelling()"); + } + synchronized (mLock) { + mCanUnbind = true; + mLock.notifyAll(); + } + } + } + public final void removeObsoletePrintJobs() { throwIfCalledOnMainThread(); synchronized (mLock) { diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java index b3f003639c1b..b6c7853c1f01 100644 --- a/services/java/com/android/server/print/UserState.java +++ b/services/java/com/android/server/print/UserState.java @@ -240,6 +240,10 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks { if (printJobInfo == null) { return; } + + // Take a note that we are trying to cancel the job. + mSpooler.setPrintJobCancelling(printJobId, true); + if (printJobInfo.getState() != PrintJobInfo.STATE_FAILED) { ComponentName printServiceName = printJobInfo.getPrinterId().getServiceName(); RemotePrintService printService = null; diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 2798104a99ac..afa4f78b51de 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -24,6 +24,7 @@ import static com.android.server.wm.WindowManagerService.TAG; import android.app.ActivityManager.StackBoxInfo; import android.graphics.Rect; import android.graphics.Region; +import android.os.Debug; import android.util.Slog; import android.view.Display; import android.view.DisplayInfo; @@ -322,7 +323,8 @@ class DisplayContent { * @return true if a change was made, false otherwise. */ boolean moveHomeStackBox(boolean toTop) { - if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop); + if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" + + Debug.getCallers(4)); switch (mStackBoxes.size()) { case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!"); case 1: return false; // Only the home StackBox exists. diff --git a/services/java/com/android/server/wm/FocusedStackFrame.java b/services/java/com/android/server/wm/FocusedStackFrame.java index 365b277c9525..cc48b867f6df 100644 --- a/services/java/com/android/server/wm/FocusedStackFrame.java +++ b/services/java/com/android/server/wm/FocusedStackFrame.java @@ -63,7 +63,7 @@ class FocusedStackFrame { } private void draw(Rect bounds, int color) { - if (DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() + + if (false && DEBUG_STACK) Slog.i(TAG, "draw: bounds=" + bounds.toShortString() + " color=" + Integer.toHexString(color)); mTmpDrawRect.set(bounds); Canvas c = null; @@ -100,7 +100,7 @@ class FocusedStackFrame { } private void positionSurface(Rect bounds) { - if (DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString()); + if (false && DEBUG_STACK) Slog.i(TAG, "positionSurface: bounds=" + bounds.toShortString()); mSurfaceControl.setSize(bounds.width(), bounds.height()); mSurfaceControl.setPosition(bounds.left, bounds.top); } @@ -108,7 +108,7 @@ class FocusedStackFrame { // Note: caller responsible for being inside // Surface.openTransaction() / closeTransaction() public void setVisibility(boolean on) { - if (DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on + + if (false && DEBUG_STACK) Slog.i(TAG, "setVisibility: on=" + on + " mLastBounds=" + mLastBounds.toShortString() + " mBounds=" + mBounds.toShortString()); if (mSurfaceControl == null) { @@ -132,7 +132,7 @@ class FocusedStackFrame { } public void setBounds(Rect bounds) { - if (DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds); + if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds); mBounds.set(bounds); } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 9bbaf603d313..aa8851ce5030 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -187,7 +187,7 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_SURFACE_TRACE = false; static final boolean DEBUG_WINDOW_TRACE = false; static final boolean DEBUG_TASK_MOVEMENT = false; - static final boolean DEBUG_STACK = false; + static final boolean DEBUG_STACK = true; static final boolean SHOW_SURFACE_ALLOC = false; static final boolean SHOW_TRANSACTIONS = false; static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS; @@ -2367,10 +2367,10 @@ public class WindowManagerService extends IWindowManager.Stub } if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v( - TAG, "Remove " + win + " client=" - + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) - + ", surface=" + win.mWinAnimator.mSurfaceControl, - new RuntimeException("here").fillInStackTrace()); + TAG, "Remove " + win + " client=" + + Integer.toHexString(System.identityHashCode(win.mClient.asBinder())) + + ", surface=" + win.mWinAnimator.mSurfaceControl + " Callers=" + + Debug.getCallers(4)); final long origId = Binder.clearCallingIdentity(); @@ -3386,9 +3386,9 @@ public class WindowManagerService extends IWindowManager.Stub throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); } Task task = new Task(atoken, stack, userId); + mTaskIdToTask.put(taskId, task); stack.addTask(task, true); stack.getDisplayContent().moveStack(stack, true); - mTaskIdToTask.put(taskId, task); return task; } @@ -4724,23 +4724,6 @@ public class WindowManagerService extends IWindowManager.Stub return index; } - private void moveHomeTasksLocked(boolean toTop) { - final DisplayContent displayContent = getDefaultDisplayContentLocked(); - if (toTop ^ displayContent.homeOnTop()) { - final ArrayList<Task> tasks = displayContent.getHomeStack().getTasks(); - final int numTasks = tasks.size(); - for (int i = 0; i < numTasks; ++i) { - if (toTop) { - // Keep pulling the bottom task off and moving it to the top. - moveTaskToTop(tasks.get(0).taskId); - } else { - // Keep pulling the top task off and moving it to the bottom. - moveTaskToBottom(tasks.get(numTasks - 1).taskId); - } - } - } - } - void moveStackWindowsLocked(TaskStack stack) { DisplayContent displayContent = stack.getDisplayContent(); @@ -4797,15 +4780,9 @@ public class WindowManagerService extends IWindowManager.Stub final TaskStack stack = task.mStack; final DisplayContent displayContent = task.getDisplayContent(); final boolean isHomeStackTask = stack.isHomeStack(); - final boolean homeIsOnTop = displayContent.homeOnTop(); - if (!isHomeStackTask && homeIsOnTop) { - // First move move the home tasks all to the bottom to rearrange the windows. - moveHomeTasksLocked(false); - // Now move the stack itself. - displayContent.moveHomeStackBox(false); - } else if (isHomeStackTask && !homeIsOnTop) { - // Move the stack to the top. - displayContent.moveHomeStackBox(true); + if (isHomeStackTask != displayContent.homeOnTop()) { + // First move the stack itself. + displayContent.moveHomeStackBox(isHomeStackTask); } stack.moveTaskToTop(task); displayContent.moveStack(stack, true); @@ -5206,6 +5183,11 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager.setInputFilter(filter); } + @Override + public void setTouchExplorationEnabled(boolean enabled) { + mPolicy.setTouchExplorationEnabled(enabled); + } + public void setCurrentUser(final int newUserId) { synchronized (mWindowMap) { int oldUserId = mCurrentUserId; @@ -9468,9 +9450,8 @@ public class WindowManagerService extends IWindowManager.Stub //Slog.i(TAG, "Waiting for drawn " + win + ": removed=" // + win.mRemoved + " visible=" + win.isVisibleLw() // + " shown=" + win.mSurfaceShown); - if (win.mRemoved || !win.isVisibleLw()) { - // Window has been removed or made invisible; no draw - // will now happen, so stop waiting. + if (win.mRemoved) { + // Window has been removed; no draw will now happen, so stop waiting. Slog.w(TAG, "Aborted waiting for drawn: " + pair.first); try { pair.second.sendResult(null); @@ -9505,6 +9486,7 @@ public class WindowManagerService extends IWindowManager.Stub checkDrawnWindowsLocked(); return true; } + Slog.i(TAG, "waitForWindowDrawn: win null"); } } return false; diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 69785510789c..e3c664b4066c 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -20,6 +20,7 @@ import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.location.Country; import android.location.CountryDetector; import android.net.Uri; import android.provider.ContactsContract.CommonDataKinds.Phone; @@ -561,17 +562,23 @@ public class CallerInfo { * is in. */ private static String getCurrentCountryIso(Context context, Locale locale) { - String countryIso; - CountryDetector detector = (CountryDetector) context.getSystemService( - Context.COUNTRY_DETECTOR); - if (detector != null) { - countryIso = detector.detectCountry().getCountryIso(); - } else { - countryIso = locale.getCountry(); - Rlog.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " - + countryIso); - } - return countryIso; + String countryIso = null; + CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + Country country = detector.detectCountry(); + if (country != null) { + countryIso = country.getCountryIso(); + } else { + Rlog.e(TAG, "CountryDetector.detectCountry() returned null."); + } + } + if (countryIso == null) { + countryIso = locale.getCountry(); + Rlog.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + + countryIso); + } + return countryIso; } /** diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index 647f014db83a..3e8db065ea1d 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -215,4 +215,26 @@ interface ISms { * Requires system permission. */ void setPremiumSmsPermission(String packageName, int permission); + + /** + * SMS over IMS is supported if IMS is registered and SMS is supported + * on IMS. + * + * @return true if SMS over IMS is supported, false otherwise + * + * @see #getImsSmsFormat() + */ + boolean isImsSmsSupported(); + + /** + * Gets SMS format supported on IMS. SMS over IMS format is + * either 3GPP or 3GPP2. + * + * @return android.telephony.SmsMessage.FORMAT_3GPP, + * android.telephony.SmsMessage.FORMAT_3GPP2 + * or android.telephony.SmsMessage.FORMAT_UNKNOWN + * + * @see #isImsSmsSupported() + */ + String getImsSmsFormat(); } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 923fef280867..821a11cb3b0b 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -263,6 +263,8 @@ cat include/telephony/ril.h | \ int RIL_REQUEST_GET_CELL_INFO_LIST = 109; int RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110; int RIL_REQUEST_SET_INITIAL_ATTACH_APN = 111; + int RIL_REQUEST_IMS_REGISTRATION_STATE = 112; + int RIL_REQUEST_IMS_SEND_SMS = 113; int RIL_UNSOL_RESPONSE_BASE = 1000; int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000; int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001; @@ -301,4 +303,5 @@ cat include/telephony/ril.h | \ int RIL_UNSOL_RIL_CONNECTED = 1034; int RIL_UNSOL_VOICE_RADIO_TECH_CHANGED = 1035; int RIL_UNSOL_CELL_INFO_LIST = 1036; + int RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1037; } diff --git a/telephony/java/com/android/internal/telephony/SmsConstants.java b/telephony/java/com/android/internal/telephony/SmsConstants.java index 1ccdc3b24eef..2449108f22c4 100644 --- a/telephony/java/com/android/internal/telephony/SmsConstants.java +++ b/telephony/java/com/android/internal/telephony/SmsConstants.java @@ -62,6 +62,12 @@ public class SmsConstants { } /** + * Indicates unknown format SMS message. + * @hide pending API council approval + */ + public static final String FORMAT_UNKNOWN = "unknown"; + + /** * Indicates a 3GPP format SMS message. * @hide pending API council approval */ diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 5f944f6107f5..661bd41632bc 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -282,6 +282,18 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public List<ResolveInfo> queryIntentContentProvidersAsUser( + Intent intent, int flags, int userId) { + throw new UnsupportedOperationException(); + } + + @Override + public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) { + throw new UnsupportedOperationException(); + } + @Override public ProviderInfo resolveContentProvider(String name, int flags) { throw new UnsupportedOperationException(); diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 52ebaf0f7775..f2e525481399 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -636,6 +636,30 @@ bool isInProductList(const String16& needle, const String16& haystack) { return false; } +/* + * A simple container that holds a resource type and name. It is ordered first by type then + * by name. + */ +struct type_ident_pair_t { + String16 type; + String16 ident; + + type_ident_pair_t() { }; + type_ident_pair_t(const String16& t, const String16& i) : type(t), ident(i) { } + type_ident_pair_t(const type_ident_pair_t& o) : type(o.type), ident(o.ident) { } + inline bool operator < (const type_ident_pair_t& o) const { + int cmp = compare_type(type, o.type); + if (cmp < 0) { + return true; + } else if (cmp > 0) { + return false; + } else { + return strictly_order_type(ident, o.ident); + } + } +}; + + status_t parseAndAddEntry(Bundle* bundle, const sp<AaptFile>& in, ResXMLTree* block, @@ -650,6 +674,7 @@ status_t parseAndAddEntry(Bundle* bundle, const String16& product, bool pseudolocalize, const bool overwrite, + KeyedVector<type_ident_pair_t, bool>* skippedResourceNames, ResourceTable* outTable) { status_t err; @@ -684,6 +709,13 @@ status_t parseAndAddEntry(Bundle* bundle, if (bundleProduct[0] == '\0') { if (strcmp16(String16("default").string(), product.string()) != 0) { + /* + * This string has a product other than 'default'. Do not add it, + * but record it so that if we do not see the same string with + * product 'default' or no product, then report an error. + */ + skippedResourceNames->replaceValueFor( + type_ident_pair_t(curType, ident), true); return NO_ERROR; } } else { @@ -797,6 +829,11 @@ status_t compileResourceFile(Bundle* bundle, DefaultKeyedVector<String16, uint32_t> nextPublicId(0); + // Stores the resource names that were skipped. Typically this happens when + // AAPT is invoked without a product specified and a resource has no + // 'default' product attribute. + KeyedVector<type_ident_pair_t, bool> skippedResourceNames; + ResXMLTree::event_code_t code; do { code = block.next(); @@ -1544,7 +1581,7 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, *curTag, curIsStyled, curFormat, curIsFormatted, - product, false, overwrite, outTable); + product, false, overwrite, &skippedResourceNames, outTable); if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? hasErrors = localHasErrors = true; @@ -1557,7 +1594,7 @@ status_t compileResourceFile(Bundle* bundle, err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, ident, *curTag, curIsStyled, curFormat, curIsFormatted, product, - true, overwrite, outTable); + true, overwrite, &skippedResourceNames, outTable); if (err != NO_ERROR) { hasErrors = localHasErrors = true; } @@ -1596,6 +1633,30 @@ status_t compileResourceFile(Bundle* bundle, } } + // For every resource defined, there must be exist one variant with a product attribute + // set to 'default' (or no product attribute at all). + // We check to see that for every resource that was ignored because of a mismatched + // product attribute, some product variant of that resource was processed. + for (size_t i = 0; i < skippedResourceNames.size(); i++) { + if (skippedResourceNames[i]) { + const type_ident_pair_t& p = skippedResourceNames.keyAt(i); + if (!outTable->hasBagOrEntry(myPackage, p.type, p.ident)) { + const char* bundleProduct = + (bundle->getProduct() == NULL) ? "" : bundle->getProduct(); + fprintf(stderr, "In resource file %s: %s\n", + in->getPrintableSource().string(), + curParams.toString().string()); + + fprintf(stderr, "\t%s '%s' does not match product %s.\n" + "\tYou may have forgotten to include a 'default' product variant" + " of the resource.\n", + String8(p.type).string(), String8(p.ident).string(), + bundleProduct[0] == 0 ? "default" : bundleProduct); + return UNKNOWN_ERROR; + } + } + } + return hasErrors ? UNKNOWN_ERROR : NO_ERROR; } @@ -2483,8 +2544,8 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) { String16 comment(c->getComment()); typeSymbols->appendComment(String8(c->getName()), comment, c->getPos()); - //printf("Type symbol %s comment: %s\n", String8(e->getName()).string(), - // String8(comment).string()); + //printf("Type symbol [%08x] %s comment: %s\n", rid, + // String8(c->getName()).string(), String8(comment).string()); comment = c->getTypeComment(); typeSymbols->appendTypeComment(String8(c->getName()), comment); } else { diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 225b0c3f4be9..fd153af99353 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -494,4 +494,8 @@ public class IWindowManagerImpl implements IWindowManager { // TODO Auto-generated method stub return false; } + + @Override + public void setTouchExplorationEnabled(boolean enabled) { + } } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 349fe24332f4..b4c583e85076 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -2958,7 +2958,9 @@ public class WifiStateMachine extends StateMachine { if (mOperationalMode != CONNECT_MODE) { mWifiNative.disconnect(); mWifiConfigStore.disableAllNetworks(); - setWifiState(WIFI_STATE_DISABLED); + if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) { + setWifiState(WIFI_STATE_DISABLED); + } transitionTo(mScanModeState); } else { /* Driver stop may have disabled networks, enable right after start */ @@ -3533,10 +3535,7 @@ public class WifiStateMachine extends StateMachine { @Override public void exit() { - // if we're leaving before this is done, cleanup - if (mDhcpActive) { - handlePostDhcpSetup(); - } + handleNetworkDisconnect(); } @Override |