diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-03-18 10:36:07 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-03-18 10:36:07 +0100 |
commit | 813d4309fb2144b96ffcd644c71a30aadc50fd1e (patch) | |
tree | 532609cc34968f682701176114c484f5278b8349 /core/java | |
parent | 8bc386657e4bd582ea0897410523e27230a8e157 (diff) | |
parent | df301d4a64fe0dfc812b39e3f7e2c2ca4b93c305 (diff) | |
download | frameworks_base-813d4309fb2144b96ffcd644c71a30aadc50fd1e.zip frameworks_base-813d4309fb2144b96ffcd644c71a30aadc50fd1e.tar.gz frameworks_base-813d4309fb2144b96ffcd644c71a30aadc50fd1e.tar.bz2 |
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_base into replicant-6.0
Diffstat (limited to 'core/java')
80 files changed, 1444 insertions, 3251 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 8bada59..5fc3437 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1327,6 +1327,23 @@ public class ActivityManager { } /** + * Check whether the current foreground tasks belongs to a given package. + * + * @param packageName Name of the package to check for + * + * @return Whether the current foreground tasks belongs to the given package + * @hide + */ + public boolean isPackageInForeground(String packageName) { + try { + return ActivityManagerNative.getDefault().isPackageInForeground(packageName); + } catch (RemoteException e) { + // System dead, we will be dead too soon! + return false; + } + } + + /** * Completely remove the given task. * * @param taskId Identifier of the task to be removed. diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index d638de6..ff06b74 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -647,6 +647,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case IS_PACKAGE_IN_FOREGROUND_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String packageName = data.readString(); + boolean result = isPackageInForeground(packageName); + reply.writeNoException(); + reply.writeInt(result ? 1 : 0); + return true; + } + case GET_RECENT_TASKS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int maxNum = data.readInt(); @@ -3300,6 +3309,18 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); return list; } + public boolean isPackageInForeground(String packageName) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(packageName); + mRemote.transact(IS_PACKAGE_IN_FOREGROUND_TRANSACTION, data, reply, 0); + reply.readException(); + boolean result = reply.readInt() != 0; + data.recycle(); + reply.recycle(); + return result; + } public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7d3b572..782dc46 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2456,16 +2456,6 @@ public final class ActivityThread { return activity; } - private void sendAppLaunchFailureBroadcast(ActivityClientRecord r) { - String pkg = null; - if (r.packageInfo != null && !TextUtils.isEmpty(r.packageInfo.getPackageName())) { - pkg = r.packageInfo.getPackageName(); - } - Intent intent = new Intent(Intent.ACTION_APP_FAILURE, - (pkg != null)? Uri.fromParts("package", pkg, null) : null); - getSystemContext().sendBroadcast(intent); - } - private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) { int displayId = Display.DEFAULT_DISPLAY; try { @@ -4279,6 +4269,11 @@ public final class ActivityThread { configDiff = mConfiguration.updateFrom(config); config = applyCompatConfiguration(mCurDefaultDisplayDpi); + + final Theme systemTheme = getSystemContext().getTheme(); + if ((systemTheme.getChangingConfigurations() & configDiff) != 0) { + systemTheme.rebase(); + } } ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 9c0d931..c075ed6 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -24,8 +24,6 @@ import android.content.IIntentSender; import android.content.Intent; import android.content.IntentSender; import android.graphics.SurfaceTexture; -import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; import android.os.Message; import android.os.OperationCanceledException; @@ -45,6 +43,17 @@ import android.view.WindowManager; import dalvik.system.CloseGuard; import java.lang.ref.WeakReference; +import java.util.ArrayDeque; +import java.util.concurrent.Executor; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.android.internal.annotations.GuardedBy; + /** @hide */ public class ActivityView extends ViewGroup { @@ -53,9 +62,64 @@ public class ActivityView extends ViewGroup { private static final int MSG_SET_SURFACE = 1; - DisplayMetrics mMetrics = new DisplayMetrics(); + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); + private static final int MINIMUM_POOL_SIZE = 1; + private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; + private static final int KEEP_ALIVE = 1; + + private static final ThreadFactory sThreadFactory = new ThreadFactory() { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(Runnable r) { + return new Thread(r, "ActivityView #" + mCount.getAndIncrement()); + } + }; + + private static final BlockingQueue<Runnable> sPoolWorkQueue = + new LinkedBlockingQueue<Runnable>(128); + + /** + * An {@link Executor} that can be used to execute tasks in parallel. + */ + private static final Executor sExecutor = new ThreadPoolExecutor(MINIMUM_POOL_SIZE, + MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); + + + private static class SerialExecutor implements Executor { + private final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); + private Runnable mActive; + + public synchronized void execute(final Runnable r) { + mTasks.offer(new Runnable() { + public void run() { + try { + r.run(); + } finally { + scheduleNext(); + } + } + }); + if (mActive == null) { + scheduleNext(); + } + } + + protected synchronized void scheduleNext() { + if ((mActive = mTasks.poll()) != null) { + sExecutor.execute(mActive); + } + } + } + + private final SerialExecutor mExecutor = new SerialExecutor(); + + private final int mDensityDpi; private final TextureView mTextureView; + + @GuardedBy("mActivityContainerLock") private ActivityContainerWrapper mActivityContainer; + private Object mActivityContainerLock = new Object(); + private Activity mActivity; private int mWidth; private int mHeight; @@ -63,8 +127,6 @@ public class ActivityView extends ViewGroup { private int mLastVisibility; private ActivityViewCallback mActivityViewCallback; - private HandlerThread mThread = new HandlerThread("ActivityViewThread"); - private Handler mHandler; public ActivityView(Context context) { this(context, null); @@ -97,28 +159,14 @@ public class ActivityView extends ViewGroup { + e); } - mThread.start(); - mHandler = new Handler(mThread.getLooper()) { - @Override - public void handleMessage(Message msg) { - super.handleMessage(msg); - if (msg.what == MSG_SET_SURFACE) { - try { - mActivityContainer.setSurface((Surface) msg.obj, msg.arg1, msg.arg2, - mMetrics.densityDpi); - } catch (RemoteException e) { - throw new RuntimeException( - "ActivityView: Unable to set surface of ActivityContainer. " + e); - } - } - } - }; mTextureView = new TextureView(context); mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); addView(mTextureView); WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(mMetrics); + DisplayMetrics metrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(metrics); + mDensityDpi = metrics.densityDpi; mLastVisibility = getVisibility(); @@ -131,15 +179,13 @@ public class ActivityView extends ViewGroup { } @Override - protected void onVisibilityChanged(View changedView, int visibility) { + protected void onVisibilityChanged(View changedView, final int visibility) { super.onVisibilityChanged(changedView, visibility); if (mSurface != null && (visibility == View.GONE || mLastVisibility == View.GONE)) { - Message msg = Message.obtain(mHandler, MSG_SET_SURFACE); - msg.obj = (visibility == View.GONE) ? null : mSurface; - msg.arg1 = mWidth; - msg.arg2 = mHeight; - mHandler.sendMessage(msg); + if (DEBUG) Log.v(TAG, "visibility changed; enqueing runnable"); + final Surface surface = (visibility == View.GONE) ? null : mSurface; + setSurfaceAsync(surface, mWidth, mHeight, mDensityDpi, false); } mLastVisibility = visibility; } @@ -230,8 +276,10 @@ public class ActivityView extends ViewGroup { Log.e(TAG, "Duplicate call to release"); return; } - mActivityContainer.release(); - mActivityContainer = null; + synchronized (mActivityContainerLock) { + mActivityContainer.release(); + mActivityContainer = null; + } if (mSurface != null) { mSurface.release(); @@ -241,21 +289,37 @@ public class ActivityView extends ViewGroup { mTextureView.setSurfaceTextureListener(null); } - private void attachToSurfaceWhenReady() { - final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); - if (surfaceTexture == null || mSurface != null) { - // Either not ready to attach, or already attached. - return; - } - - mSurface = new Surface(surfaceTexture); - try { - mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi); - } catch (RemoteException e) { - mSurface.release(); - mSurface = null; - throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e); - } + private void setSurfaceAsync(final Surface surface, final int width, final int height, + final int densityDpi, final boolean callback) { + mExecutor.execute(new Runnable() { + public void run() { + try { + synchronized (mActivityContainerLock) { + if (mActivityContainer != null) { + mActivityContainer.setSurface(surface, width, height, densityDpi); + } + } + } catch (RemoteException e) { + throw new RuntimeException( + "ActivityView: Unable to set surface of ActivityContainer. ", + e); + } + if (callback) { + post(new Runnable() { + @Override + public void run() { + if (mActivityViewCallback != null) { + if (surface != null) { + mActivityViewCallback.onSurfaceAvailable(ActivityView.this); + } else { + mActivityViewCallback.onSurfaceDestroyed(ActivityView.this); + } + } + } + }); + } + } + }); } /** @@ -306,10 +370,8 @@ public class ActivityView extends ViewGroup { + height); mWidth = width; mHeight = height; - attachToSurfaceWhenReady(); - if (mActivityViewCallback != null) { - mActivityViewCallback.onSurfaceAvailable(ActivityView.this); - } + mSurface = new Surface(surfaceTexture); + setSurfaceAsync(mSurface, mWidth, mHeight, mDensityDpi, true); } @Override @@ -329,15 +391,7 @@ public class ActivityView extends ViewGroup { if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed"); mSurface.release(); mSurface = null; - try { - mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi); - } catch (RemoteException e) { - throw new RuntimeException( - "ActivityView: Unable to set surface of ActivityContainer. " + e); - } - if (mActivityViewCallback != null) { - mActivityViewCallback.onSurfaceDestroyed(ActivityView.this); - } + setSurfaceAsync(null, mWidth, mHeight, mDensityDpi, true); return true; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 479010d..d443d80 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -40,8 +40,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.AssetManager; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; -import android.content.res.IThemeService; -import android.content.res.ThemeManager; import android.content.res.Resources; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index a27f9c8..6370268 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -129,6 +129,7 @@ public interface IActivityManager extends IInterface { ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException; public Point getAppTaskThumbnailSize() throws RemoteException; public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException; + public boolean isPackageInForeground(String packageName) throws RemoteException; public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) throws RemoteException; public ActivityManager.TaskThumbnail getTaskThumbnail(int taskId) throws RemoteException; @@ -870,4 +871,5 @@ public interface IActivityManager extends IInterface { = IBinder.FIRST_CALL_TRANSACTION+299; int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300; int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301; + int IS_PACKAGE_IN_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+302; } diff --git a/core/java/android/content/res/IThemeChangeListener.aidl b/core/java/android/app/IBatteryService.aidl index a2e2abd..196159b 100644 --- a/core/java/android/content/res/IThemeChangeListener.aidl +++ b/core/java/android/app/IBatteryService.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project +/** + * Copyright (c) 2016, The CyanogenMod 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 + * 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, @@ -13,10 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.res; -/** {@hide} */ -oneway interface IThemeChangeListener { - void onProgress(int progress); - void onFinish(boolean isSuccess); +package android.app; + +/** + * System private API for talking with the battery service. + * + * {@hide} + */ +interface IBatteryService { + boolean isDockBatterySupported(); } diff --git a/core/java/android/app/IconPackHelper.java b/core/java/android/app/IconPackHelper.java index 627330f..80fb401 100644 --- a/core/java/android/app/IconPackHelper.java +++ b/core/java/android/app/IconPackHelper.java @@ -25,7 +25,6 @@ import java.util.Map; import java.util.Random; import android.content.pm.PackageInfo; -import android.content.res.IThemeService; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -44,7 +43,10 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; import android.util.TypedValue; + import com.android.internal.util.cm.palette.Palette; + +import org.cyanogenmod.internal.themes.IIconCacheManager; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; @@ -103,6 +105,12 @@ public class IconPackHelper { private static final float DEFAULT_SCALE = 1.0f; private static final int COMPOSED_ICON_COOKIE = 128; + private static final String ICON_CACHE_SERVICE = "cmiconcache"; + + public static final String SYSTEM_THEME_PATH = "/data/system/theme"; + public static final String SYSTEM_THEME_ICON_CACHE_DIR = SYSTEM_THEME_PATH + + File.separator + "icons"; + private final Context mContext; private Map<ComponentName, String> mIconPackResourceMap; private String mLoadedIconPackName; @@ -410,15 +418,12 @@ public class IconPackHelper { String prefixPath; String iconApkPath; - String iconResPath; if (info.isLegacyIconPackApk) { - iconResPath = ""; iconApkPath = ""; prefixPath = ""; } else { prefixPath = ThemeUtils.ICONS_PATH; //path inside APK iconApkPath = ThemeUtils.getIconPackApkPath(packageName); - iconResPath = ThemeUtils.getIconPackResPath(packageName); } AssetManager assets = new AssetManager(); @@ -587,11 +592,11 @@ public class IconPackHelper { public static class IconCustomizer { private static final Random sRandom = new Random(); - private static final IThemeService sThemeService; + private static final IIconCacheManager sIconCacheManager; static { - sThemeService = IThemeService.Stub.asInterface( - ServiceManager.getService(Context.THEME_SERVICE)); + sIconCacheManager = IIconCacheManager.Stub.asInterface( + ServiceManager.getService(ICON_CACHE_SERVICE)); } public static Drawable getComposedIconDrawable(Drawable icon, Context context, @@ -802,7 +807,7 @@ public class IconPackHelper { private static boolean cacheComposedIcon(Bitmap bmp, String path) { try { - return sThemeService.cacheComposedIcon(bmp, path); + return sIconCacheManager.cacheComposedIcon(bmp, path); } catch (RemoteException e) { Log.e(TAG, "Unable to cache icon.", e); } @@ -811,7 +816,7 @@ public class IconPackHelper { } private static String getCachedIconPath(String pkgName, int resId, int density) { - return String.format("%s/%s", ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR, + return String.format("%s/%s", SYSTEM_THEME_ICON_CACHE_DIR, getCachedIconName(pkgName, resId, density)); } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index cd07c9c..d8e01cd 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -45,6 +45,7 @@ import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.util.MathUtils; +import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -62,6 +63,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.Set; /** * A class that represents how a persistent notification is to be presented to @@ -960,6 +963,9 @@ public class Notification implements Parcelable private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras, RemoteInput[] remoteInputs) { this.mIcon = icon; + if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) { + this.icon = icon.getResId(); + } this.title = title; this.actionIntent = intent; this.mExtras = extras != null ? extras : new Bundle(); @@ -1607,13 +1613,23 @@ public class Notification implements Parcelable bigContentView = null; headsUpContentView = null; mLargeIcon = null; - if (extras != null) { - extras.remove(Notification.EXTRA_LARGE_ICON); - extras.remove(Notification.EXTRA_LARGE_ICON_BIG); - extras.remove(Notification.EXTRA_PICTURE); - extras.remove(Notification.EXTRA_BIG_TEXT); + if (extras != null && !extras.isEmpty()) { // Prevent light notifications from being rebuilt. extras.remove(Builder.EXTRA_NEEDS_REBUILD); + final Set<String> keyset = extras.keySet(); + final int N = keyset.size(); + final String[] keys = keyset.toArray(new String[N]); + for (int i=0; i<N; i++) { + final String key = keys[i]; + final Object obj = extras.get(key); + if (obj != null && + ( obj instanceof Parcelable + || obj instanceof Parcelable[] + || obj instanceof SparseArray + || obj instanceof ArrayList)) { + extras.remove(key); + } + } } } @@ -4619,7 +4635,7 @@ public class Notification implements Parcelable * Size value for use with {@link #setCustomSizePreset} to show this notification with * default sizing. * <p>For custom display notifications created using {@link #setDisplayIntent}, - * the default is {@link #SIZE_LARGE}. All other notifications size automatically based + * the default is {@link #SIZE_MEDIUM}. All other notifications size automatically based * on their content. */ public static final int SIZE_DEFAULT = 0; diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index 7492cd0..e2d0537 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -625,7 +625,8 @@ public class ResourcesManager { String targetPackagePath = piTarget.applicationInfo.sourceDir; String prefixPath = ThemeUtils.getOverlayPathToTarget(basePackageName); - String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName, piTheme); + String resCachePath = ThemeUtils.getTargetCacheDir(piTarget.packageName, + piTheme.packageName); String resApkPath = resCachePath + "/resources.apk"; String idmapPath = ThemeUtils.getIdmapPath(piTarget.packageName, piTheme.packageName); int cookie = assets.addOverlayPath(idmapPath, themePath, resApkPath, @@ -639,7 +640,8 @@ public class ResourcesManager { if (!piTarget.isThemeApk && !"android".equals(basePackageName) && piTheme.mOverlayTargets.contains("android")) { - String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, piTheme); + String resCachePath= ThemeUtils.getTargetCacheDir(piAndroid.packageName, + piTheme.packageName); String prefixPath = ThemeUtils.getOverlayPathToTarget(piAndroid.packageName); String targetPackagePath = piAndroid.applicationInfo.publicSourceDir; String resApkPath = resCachePath + "/resources.apk"; @@ -742,7 +744,7 @@ public class ResourcesManager { String themePath = piTheme.applicationInfo.publicSourceDir; String prefixPath = ThemeUtils.COMMON_RES_PATH; String resCachePath = - ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme); + ThemeUtils.getTargetCacheDir(ThemeUtils.COMMON_RES_TARGET, piTheme.packageName); String resApkPath = resCachePath + "/resources.apk"; int cookie = assets.addCommonOverlayPath(themePath, resApkPath, prefixPath); diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 5e8ad68..fad3f62 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -92,6 +92,7 @@ public class StatusBarManager { public static final int CAMERA_LAUNCH_SOURCE_WIGGLE = 0; public static final int CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP = 1; + public static final int CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE = 2; private Context mContext; private IStatusBarService mService; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 08f4efd..34c967f 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -37,9 +37,7 @@ import android.content.IRestrictionsManager; import android.content.RestrictionsManager; import android.content.pm.ILauncherApps; import android.content.pm.LauncherApps; -import android.content.res.IThemeService; import android.content.res.Resources; -import android.content.res.ThemeManager; import android.hardware.ConsumerIrManager; import android.hardware.ISerialManager; import android.hardware.SensorManager; @@ -256,7 +254,9 @@ final class SystemServiceRegistry { new StaticServiceFetcher<BatteryManager>() { @Override public BatteryManager createService() { - return new BatteryManager(); + IBinder b = ServiceManager.getService(Context.BATTERY_SERVICE); + IBatteryService service = IBatteryService.Stub.asInterface(b); + return new BatteryManager(service); }}); registerService(Context.NFC_SERVICE, NfcManager.class, @@ -706,15 +706,6 @@ final class SystemServiceRegistry { public RadioManager createService(ContextImpl ctx) { return new RadioManager(ctx); }}); - - registerService(Context.THEME_SERVICE, ThemeManager.class, - new CachedServiceFetcher<ThemeManager>() { - public ThemeManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.THEME_SERVICE); - IThemeService service = IThemeService.Stub.asInterface(b); - return new ThemeManager(ctx.getOuterContext(), - service); - }}); } /** diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index 7718a36..0335e28 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -21,6 +21,8 @@ import android.content.pm.PackageManager; import android.content.res.XmlResourceParser; import android.os.*; import android.os.Process; +import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; import android.system.ErrnoException; import android.system.Os; import android.text.TextUtils; @@ -207,6 +209,8 @@ public class FullBackup { final int mFullBackupContent; final PackageManager mPackageManager; + final StorageManager mStorageManager; + final StorageVolume[] mVolumes; final String mPackageName; /** @@ -230,6 +234,15 @@ public class FullBackup { } else { return null; } + } else if (domainToken.startsWith(FullBackup.SHARED_PREFIX)) { + int slash = domainToken.indexOf('/'); + int i = Integer.parseInt(domainToken.substring(slash + 1)); + + if (i < mVolumes.length) { + return mVolumes[i].getPath(); + } else { + Log.e(TAG, "Could not find volume for " + domainToken); + } } else if (domainToken.equals(FullBackup.NO_BACKUP_TREE_TOKEN)) { return NOBACKUP_DIR.getCanonicalPath(); } @@ -263,6 +276,8 @@ public class FullBackup { SHAREDPREF_DIR = context.getSharedPrefsFile("foo").getParentFile(); CACHE_DIR = context.getCacheDir(); NOBACKUP_DIR = context.getNoBackupFilesDir(); + mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE); + mVolumes = mStorageManager.getVolumeList(); if (android.os.Process.myUid() != Process.SYSTEM_UID) { EXTERNAL_DIR = context.getExternalFilesDir(null); } else { diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index 0fce4e2..a88aa31 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -165,14 +165,18 @@ public final class UsageStats implements Parcelable { mPackageName + "' with UsageStats for package '" + right.mPackageName + "'."); } - if (right.mEndTimeStamp > mEndTimeStamp) { + if (right.mBeginTimeStamp > mBeginTimeStamp) { + // The incoming UsageStat begins after this one, so use its last time used fields + // as the source of truth. + // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with + // regards to their mEndTimeStamp. mLastEvent = right.mLastEvent; - mEndTimeStamp = right.mEndTimeStamp; mLastTimeUsed = right.mLastTimeUsed; mBeginIdleTime = right.mBeginIdleTime; mLastTimeSystemUsed = right.mLastTimeSystemUsed; } mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp); + mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp); mTotalTimeInForeground += right.mTotalTimeInForeground; mLaunchCount += right.mLaunchCount; } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 24beba6..f924bc1 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -95,7 +95,7 @@ import java.util.UUID; */ public final class BluetoothAdapter { private static final String TAG = "BluetoothAdapter"; - private static final boolean DBG = true; + private static final boolean DBG = false; private static final boolean VDBG = false; /** diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e742b2b..b4006de 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -25,6 +25,7 @@ import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.os.ParcelUuid; +import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -823,6 +824,9 @@ public final class BluetoothDevice implements Parcelable { return false; } try { + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, TRANSPORT_AUTO); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -854,6 +858,9 @@ public final class BluetoothDevice implements Parcelable { throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); } try { + Log.i(TAG, "createBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.createBond(this, transport); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -922,6 +929,9 @@ public final class BluetoothDevice implements Parcelable { return false; } try { + Log.i(TAG, "cancelBondProcess() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.cancelBondProcess(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; @@ -943,6 +953,9 @@ public final class BluetoothDevice implements Parcelable { return false; } try { + Log.i(TAG, "removeBond() for device " + getAddress() + + " called by pid: " + Process.myPid() + + " tid: " + Process.myTid()); return sService.removeBond(this); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 8d4742b..da81032 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; @@ -302,7 +303,7 @@ public final class BluetoothHeadset implements BluetoothProfile { ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); intent.setComponent(comp); if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { + UserHandle.CURRENT_OR_SELF)) { Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent); return false; } @@ -709,6 +710,48 @@ public final class BluetoothHeadset implements BluetoothProfile { } /** + * Sets whether audio routing is allowed. When set to {@code false}, the AG will not route any + * audio to the HF unless explicitly told to. + * This method should be used in cases where the SCO channel is shared between multiple profiles + * and must be delegated by a source knowledgeable + * Note: This is an internal function and shouldn't be exposed + * + * @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise. + * + * @hide + */ + public void setAudioRouteAllowed(boolean allowed) { + if (VDBG) log("setAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + mService.setAudioRouteAllowed(allowed); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** + * Returns whether audio routing is allowed. see {@link #setAudioRouteAllowed(boolean)}. + * Note: This is an internal function and shouldn't be exposed + * + * @hide + */ + public boolean getAudioRouteAllowed() { + if (VDBG) log("getAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioRouteAllowed(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** * Check if Bluetooth SCO audio is connected. * * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission. diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 10d851f..484a856 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -1076,6 +1076,41 @@ public final class BluetoothHeadsetClient implements BluetoothProfile { } /** + * Sets whether audio routing is allowed. + * + * Note: This is an internal function and shouldn't be exposed + */ + public void setAudioRouteAllowed(boolean allowed) { + if (VDBG) log("setAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + mService.setAudioRouteAllowed(allowed); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + } + + /** + * Returns whether audio routing is allowed. + * + * Note: This is an internal function and shouldn't be exposed + */ + public boolean getAudioRouteAllowed() { + if (VDBG) log("getAudioRouteAllowed"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioRouteAllowed(); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** * Initiates a connection of audio channel. * * It setup SCO channel with remote connected Handsfree AG device. diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java index 7b5a045..002f63f 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java @@ -19,6 +19,8 @@ package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; +import java.util.UUID; + /** * This class represents a single call, its state and properties. * It implements {@link Parcelable} for inter-process message passing. @@ -67,14 +69,21 @@ public final class BluetoothHeadsetClientCall implements Parcelable { private String mNumber; private boolean mMultiParty; private final boolean mOutgoing; + private final UUID mUUID; /** * Creates BluetoothHeadsetClientCall instance. */ public BluetoothHeadsetClientCall(BluetoothDevice device, int id, int state, String number, boolean multiParty, boolean outgoing) { + this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing); + } + + public BluetoothHeadsetClientCall(BluetoothDevice device, int id, UUID uuid, int state, + String number, boolean multiParty, boolean outgoing) { mDevice = device; mId = id; + mUUID = uuid; mState = state; mNumber = number != null ? number : ""; mMultiParty = multiParty; @@ -134,6 +143,16 @@ public final class BluetoothHeadsetClientCall implements Parcelable { } /** + * Gets call's UUID. + * + * @return call uuid + * @hide + */ + public UUID getUUID() { + return mUUID; + } + + /** * Gets call's current state. * * @return state of this particular phone call. @@ -172,10 +191,16 @@ public final class BluetoothHeadsetClientCall implements Parcelable { } public String toString() { + return toString(false); + } + + public String toString(boolean loggable) { StringBuilder builder = new StringBuilder("BluetoothHeadsetClientCall{mDevice: "); - builder.append(mDevice); + builder.append(loggable ? mDevice.hashCode() : mDevice); builder.append(", mId: "); builder.append(mId); + builder.append(", mUUID: "); + builder.append(mUUID); builder.append(", mState: "); switch (mState) { case CALL_STATE_ACTIVE: builder.append("ACTIVE"); break; @@ -189,7 +214,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { default: builder.append(mState); break; } builder.append(", mNumber: "); - builder.append(mNumber); + builder.append(loggable ? mNumber.hashCode() : mNumber); builder.append(", mMultiParty: "); builder.append(mMultiParty); builder.append(", mOutgoing: "); @@ -206,8 +231,8 @@ public final class BluetoothHeadsetClientCall implements Parcelable { @Override public BluetoothHeadsetClientCall createFromParcel(Parcel in) { return new BluetoothHeadsetClientCall((BluetoothDevice)in.readParcelable(null), - in.readInt(), in.readInt(), in.readString(), - in.readInt() == 1, in.readInt() == 1); + in.readInt(), UUID.fromString(in.readString()), in.readInt(), + in.readString(), in.readInt() == 1, in.readInt() == 1); } @Override @@ -220,6 +245,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeParcelable(mDevice, 0); out.writeInt(mId); + out.writeString(mUUID.toString()); out.writeInt(mState); out.writeString(mNumber); out.writeInt(mMultiParty ? 1 : 0); diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index 0e23fad..0bb4088 100755 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -50,6 +50,8 @@ interface IBluetoothHeadset { boolean isAudioOn(); boolean connectAudio(); boolean disconnectAudio(); + void setAudioRouteAllowed(boolean allowed); + boolean getAudioRouteAllowed(); boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device); boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device); void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type); diff --git a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl index e518b7d..79ae4e4 100644 --- a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl @@ -62,6 +62,8 @@ interface IBluetoothHeadsetClient { int getAudioState(in BluetoothDevice device); boolean connectAudio(); boolean disconnectAudio(); + void setAudioRouteAllowed(boolean allowed); + boolean getAudioRouteAllowed(); Bundle getCurrentAgFeatures(in BluetoothDevice device); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index fc40a73..7ddda11 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3152,16 +3152,6 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a - * {@link android.content.res.ThemeManager} for accessing theme service. - * - * @see #getSystemService - * @see android.content.res.ThemeManager - * @hide - */ - public static final String THEME_SERVICE = "themes"; - - /** - * Use with {@link #getSystemService} to retrieve a * {@link android.nfc.NfcManager} for using NFC. * * @see #getSystemService diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2a24fe3..c06f98a 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1605,6 +1605,23 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.action.GET_PERMISSIONS_COUNT"; /** + * Broadcast action that requests list of all apps that have runtime permissions. It will + * respond to the request by sending a broadcast with action defined by + * {@link #EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT}. The response will contain + * {@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT}, as well as + * {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT}, with contents described below or + * a null upon failure. + * + * <p>{@link #EXTRA_GET_PERMISSIONS_APP_LIST_RESULT} will contain a list of package names of + * apps that have runtime permissions. {@link #EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT} + * will contain the list of app labels corresponding ot the apps in the first list. + * + * @hide + */ + public static final String ACTION_GET_PERMISSIONS_PACKAGES + = "android.intent.action.GET_PERMISSIONS_PACKAGES"; + + /** * Extra included in response to {@link #ACTION_GET_PERMISSIONS_COUNT}. * @hide */ @@ -1619,6 +1636,28 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.extra.GET_PERMISSIONS_GROUP_LIST_RESULT"; /** + * String list of apps that have one or more runtime permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_APP_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_APP_LIST_RESULT"; + + /** + * String list of app labels for apps that have one or more runtime permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_APP_LABEL_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_APP_LABEL_LIST_RESULT"; + + /** + * Boolean list describing if the app is a system app for apps that have one or more runtime + * permissions. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT + = "android.intent.extra.GET_PERMISSIONS_IS_SYSTEM_APP_LIST_RESULT"; + + /** * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_COUNT} broadcasts. * @hide */ @@ -1626,6 +1665,13 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.extra.GET_PERMISSIONS_RESONSE_INTENT"; /** + * Required extra to be sent with {@link #ACTION_GET_PERMISSIONS_PACKAGES} broadcasts. + * @hide + */ + public static final String EXTRA_GET_PERMISSIONS_PACKAGES_RESPONSE_INTENT + = "android.intent.extra.GET_PERMISSIONS_PACKAGES_RESONSE_INTENT"; + + /** * Activity action: Launch UI to manage which apps have a given permission. * <p> * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access @@ -2881,21 +2927,6 @@ public class Intent implements Parcelable, Cloneable { "android.intent.action.QUICK_CLOCK"; /** - * Broadcast Action: Indicate that unrecoverable error happened during app launch. - * Could indicate that curently applied theme is malicious. - * @hide - */ - public static final String ACTION_APP_FAILURE = - "com.tmobile.intent.action.APP_FAILURE"; - - /** - * Broadcast Action: Request to reset the unrecoverable errors count to 0. - * @hide - */ - public static final String ACTION_APP_FAILURE_RESET = - "com.tmobile.intent.action.APP_FAILURE_RESET"; - - /** * Activity Action: Shows the brightness setting dialog. * @hide */ @@ -3081,6 +3112,39 @@ public class Intent implements Parcelable, Cloneable { public static final String ACTION_DOZE_PULSE_STARTING = "android.intent.action.DOZE_PULSE_STARTING"; + /** + * Broadcast action: reports when a new thermal event has been reached. When the device + * is reaching its maximum temperatue, the thermal level reported + * {@hide} + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_THERMAL_EVENT = "android.intent.action.THERMAL_EVENT"; + + /** {@hide} */ + public static final String EXTRA_THERMAL_STATE = "android.intent.extra.THERMAL_STATE"; + + /** + * Thermal state when the device is normal. This state is sent in the + * {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_NORMAL = 0; + + /** + * Thermal state where the device is approaching its maximum threshold. This state is sent in + * the {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_WARNING = 1; + + /** + * Thermal state where the device has reached its maximum threshold. This state is sent in the + * {@link ACTION_THERMAL_EVENT} broadcast as {@link EXTRA_THERMAL_STATE}. + * {@hide} + */ + public static final int EXTRA_THERMAL_STATE_EXCEEDED = 2; + + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent categories (see addCategory()). @@ -3183,6 +3247,13 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_HOME = "android.intent.category.HOME"; /** + * This is the home activity that is displayed when the device is finished setting up and ready + * for use. + * @hide + */ + @SdkConstant(SdkConstantType.INTENT_CATEGORY) + public static final String CATEGORY_HOME_MAIN = "android.intent.category.HOME_MAIN"; + /** * This is the setup wizard activity, that is the first activity that is displayed * when the user sets up the device for the first time. * @hide @@ -3282,14 +3353,6 @@ public class Intent implements Parcelable, Cloneable { @SdkConstant(SdkConstantType.INTENT_CATEGORY) public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE"; - /** - * Used to indicate that a theme package has been installed or un-installed. - * - * @hide - */ - public static final String CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE = - "com.tmobile.intent.category.THEME_PACKAGE_INSTALL_STATE_CHANGE"; - // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Application launch intent categories (see addCategory()). diff --git a/core/java/android/content/pm/ThemeUtils.java b/core/java/android/content/pm/ThemeUtils.java index e41523c..07e73b5 100644 --- a/core/java/android/content/pm/ThemeUtils.java +++ b/core/java/android/content/pm/ThemeUtils.java @@ -15,112 +15,30 @@ */ package android.content.pm; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.IntentFilter; -import android.content.res.AssetManager; -import android.content.res.Configuration; import android.content.res.ThemeConfig; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.FileUtils; -import android.os.SystemProperties; -import android.provider.MediaStore; -import android.provider.Settings; -import android.provider.ThemesContract; -import android.provider.ThemesContract.ThemesColumns; import android.text.TextUtils; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.WindowManager; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.InputStreamReader; -import java.nio.ByteBuffer; -import java.util.ArrayList; import java.util.jar.StrictJarFile; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.CRC32; import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; - -import static android.content.res.ThemeConfig.SYSTEM_DEFAULT; /** * @hide */ public class ThemeUtils { - private static final String TAG = "ThemeUtils"; + private static final String TAG = ThemeUtils.class.getSimpleName(); /* Path inside a theme APK to the overlay folder */ public static final String OVERLAY_PATH = "assets/overlays/"; public static final String ICONS_PATH = "assets/icons/"; public static final String COMMON_RES_PATH = "assets/overlays/common/"; - public static final String FONT_XML = "fonts.xml"; public static final String RESOURCE_CACHE_DIR = "/data/resource-cache/"; - public static final String IDMAP_SUFFIX = "@idmap"; - public static final String COMMON_RES_SUFFIX = ".common"; public static final String COMMON_RES_TARGET = "common"; - public static final String ICON_HASH_FILENAME = "hash"; - - // path to external theme resources, i.e. bootanimation.zip - public static final String SYSTEM_THEME_PATH = "/data/system/theme"; - public static final String SYSTEM_THEME_FONT_PATH = SYSTEM_THEME_PATH + File.separator + "fonts"; - public static final String SYSTEM_THEME_RINGTONE_PATH = SYSTEM_THEME_PATH - + File.separator + "ringtones"; - public static final String SYSTEM_THEME_NOTIFICATION_PATH = SYSTEM_THEME_PATH - + File.separator + "notifications"; - public static final String SYSTEM_THEME_ALARM_PATH = SYSTEM_THEME_PATH - + File.separator + "alarms"; - public static final String SYSTEM_THEME_ICON_CACHE_DIR = SYSTEM_THEME_PATH - + File.separator + "icons"; - // internal path to bootanimation.zip inside theme apk - public static final String THEME_BOOTANIMATION_PATH = "assets/bootanimation/bootanimation.zip"; - - public static final String SYSTEM_MEDIA_PATH = "/system/media/audio"; - public static final String SYSTEM_ALARMS_PATH = SYSTEM_MEDIA_PATH + File.separator - + "alarms"; - public static final String SYSTEM_RINGTONES_PATH = SYSTEM_MEDIA_PATH + File.separator - + "ringtones"; - public static final String SYSTEM_NOTIFICATIONS_PATH = SYSTEM_MEDIA_PATH + File.separator - + "notifications"; - - // path to asset lockscreen and wallpapers directory - public static final String LOCKSCREEN_WALLPAPER_PATH = "lockscreen"; - public static final String WALLPAPER_PATH = "wallpapers"; - - private static final String MEDIA_CONTENT_URI = "content://media/internal/audio/media"; - - // Constants for theme change broadcast - public static final String ACTION_THEME_CHANGED = "org.cyanogenmod.intent.action.THEME_CHANGED"; - public static final String CATEGORY_THEME_COMPONENT_PREFIX = "org.cyanogenmod.intent.category."; - public static final String EXTRA_COMPONENTS = "components"; - public static final String EXTRA_REQUEST_TYPE = "request_type"; - public static final String EXTRA_UPDATE_TIME = "update_time"; - - public static final int SYSTEM_TARGET_API = 0; // Package name for any app which does not have a specific theme applied private static final String DEFAULT_PKG = "default"; - private static final String SETTINGS_DB = - "/data/data/com.android.providers.settings/databases/settings.db"; - private static final String SETTINGS_SECURE_TABLE = "secure"; private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; /** @@ -156,18 +74,10 @@ public class ThemeUtils { /** * Get the path of the resource cache for the given target and theme - * @param targetPkgName - * @param themePkg + * @param targetPkgName Target app package name + * @param themePkgName Theme package name * @return Path to the resource cache for this target and theme */ - public static String getTargetCacheDir(String targetPkgName, PackageInfo themePkg) { - return getTargetCacheDir(targetPkgName, themePkg.packageName); - } - - public static String getTargetCacheDir(String targetPkgName, PackageParser.Package themePkg) { - return getTargetCacheDir(targetPkgName, themePkg.packageName); - } - public static String getTargetCacheDir(String targetPkgName, String themePkgName) { return getOverlayResourceCacheDir(themePkgName) + File.separator + targetPkgName; } @@ -181,18 +91,10 @@ public class ThemeUtils { return getOverlayResourceCacheDir(pkgName) + File.separator + "icons"; } - public static String getIconHashFile(String pkgName) { - return getIconPackDir(pkgName) + File.separator + ICON_HASH_FILENAME; - } - public static String getIconPackApkPath(String pkgName) { return getIconPackDir(pkgName) + "/resources.apk"; } - public static String getIconPackResPath(String pkgName) { - return getIconPackDir(pkgName) + "/resources.arsc"; - } - public static String getIdmapPath(String targetPkgName, String overlayPkgName) { return getTargetCacheDir(targetPkgName, overlayPkgName) + File.separator + "idmap"; } @@ -211,507 +113,6 @@ public class ThemeUtils { return COMMON_RES_TARGET; } - public static void createCacheDirIfNotExists() throws IOException { - File file = new File(RESOURCE_CACHE_DIR); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - public static void createResourcesDirIfNotExists(String targetPkgName, String overlayPkgName) - throws IOException { - createDirIfNotExists(getOverlayResourceCacheDir(overlayPkgName)); - File file = new File(getTargetCacheDir(targetPkgName, overlayPkgName)); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - public static void createIconDirIfNotExists(String pkgName) throws IOException { - createDirIfNotExists(getOverlayResourceCacheDir(pkgName)); - File file = new File(getIconPackDir(pkgName)); - if (!file.exists() && !file.mkdir()) { - throw new IOException("Could not create dir: " + file.toString()); - } - FileUtils.setPermissions(file, FileUtils.S_IRWXU - | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - - private static boolean dirExists(String dirPath) { - final File dir = new File(dirPath); - return dir.exists() && dir.isDirectory(); - } - - private static void createDirIfNotExists(String dirPath) { - if (!dirExists(dirPath)) { - File dir = new File(dirPath); - if (dir.mkdir()) { - FileUtils.setPermissions(dir, FileUtils.S_IRWXU | - FileUtils.S_IRWXG| FileUtils.S_IROTH | FileUtils.S_IXOTH, -1, -1); - } - } - } - - /** - * Create SYSTEM_THEME_PATH directory if it does not exist - */ - public static void createThemeDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_PATH); - } - - /** - * Create SYSTEM_FONT_PATH directory if it does not exist - */ - public static void createFontDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_FONT_PATH); - } - - /** - * Create SYSTEM_THEME_RINGTONE_PATH directory if it does not exist - */ - public static void createRingtoneDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_RINGTONE_PATH); - } - - /** - * Create SYSTEM_THEME_NOTIFICATION_PATH directory if it does not exist - */ - public static void createNotificationDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_NOTIFICATION_PATH); - } - - /** - * Create SYSTEM_THEME_ALARM_PATH directory if it does not exist - */ - public static void createAlarmDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_ALARM_PATH); - } - - /** - * Create SYSTEM_THEME_ICON_CACHE_DIR directory if it does not exist - */ - public static void createIconCacheDirIfNotExists() { - createDirIfNotExists(SYSTEM_THEME_ICON_CACHE_DIR); - } - - public static void clearIconCache() { - FileUtils.deleteContents(new File(SYSTEM_THEME_ICON_CACHE_DIR)); - } - - public static InputStream getInputStreamFromAsset(Context ctx, String path) throws IOException { - if (ctx == null || path == null) - return null; - InputStream is = null; - String ASSET_BASE = "file:///android_asset/"; - path = path.substring(ASSET_BASE.length()); - AssetManager assets = ctx.getAssets(); - is = assets.open(path); - return is; - } - - public static void closeQuietly(InputStream stream) { - if (stream == null) - return; - try { - stream.close(); - } catch (IOException e) { - } - } - - public static void closeQuietly(OutputStream stream) { - if (stream == null) - return; - try { - stream.close(); - } catch (IOException e) { - } - } - - /** - * Scale the boot animation to better fit the device by editing the desc.txt found - * in the bootanimation.zip - * @param context Context to use for getting an instance of the WindowManager - * @param input InputStream of the original bootanimation.zip - * @param dst Path to store the newly created bootanimation.zip - * @throws IOException - */ - public static void copyAndScaleBootAnimation(Context context, InputStream input, String dst) - throws IOException { - final OutputStream os = new FileOutputStream(dst); - final ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(os)); - final ZipInputStream bootAni = new ZipInputStream(new BufferedInputStream(input)); - ZipEntry ze; - - zos.setMethod(ZipOutputStream.STORED); - final byte[] bytes = new byte[4096]; - int len; - while ((ze = bootAni.getNextEntry()) != null) { - ZipEntry entry = new ZipEntry(ze.getName()); - entry.setMethod(ZipEntry.STORED); - entry.setCrc(ze.getCrc()); - entry.setSize(ze.getSize()); - entry.setCompressedSize(ze.getSize()); - if (!ze.getName().equals("desc.txt")) { - // just copy this entry straight over into the output zip - zos.putNextEntry(entry); - while ((len = bootAni.read(bytes)) > 0) { - zos.write(bytes, 0, len); - } - } else { - String line; - BufferedReader reader = new BufferedReader(new InputStreamReader(bootAni)); - final String[] info = reader.readLine().split(" "); - - int scaledWidth; - int scaledHeight; - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - DisplayMetrics dm = new DisplayMetrics(); - wm.getDefaultDisplay().getRealMetrics(dm); - // just in case the device is in landscape orientation we will - // swap the values since most (if not all) animations are portrait - if (dm.widthPixels > dm.heightPixels) { - scaledWidth = dm.heightPixels; - scaledHeight = dm.widthPixels; - } else { - scaledWidth = dm.widthPixels; - scaledHeight = dm.heightPixels; - } - - int width = Integer.parseInt(info[0]); - int height = Integer.parseInt(info[1]); - - if (width == height) - scaledHeight = scaledWidth; - else { - // adjust scaledHeight to retain original aspect ratio - float scale = (float)scaledWidth / (float)width; - int newHeight = (int)((float)height * scale); - if (newHeight < scaledHeight) - scaledHeight = newHeight; - } - - CRC32 crc32 = new CRC32(); - int size = 0; - ByteBuffer buffer = ByteBuffer.wrap(bytes); - line = String.format("%d %d %s\n", scaledWidth, scaledHeight, info[2]); - buffer.put(line.getBytes()); - size += line.getBytes().length; - crc32.update(line.getBytes()); - while ((line = reader.readLine()) != null) { - line = String.format("%s\n", line); - buffer.put(line.getBytes()); - size += line.getBytes().length; - crc32.update(line.getBytes()); - } - entry.setCrc(crc32.getValue()); - entry.setSize(size); - entry.setCompressedSize(size); - zos.putNextEntry(entry); - zos.write(buffer.array(), 0, size); - } - zos.closeEntry(); - } - zos.close(); - } - - public static boolean isValidAudible(String fileName) { - return (fileName != null && - (fileName.endsWith(".mp3") || fileName.endsWith(".ogg"))); - } - - public static boolean setAudible(Context context, File ringtone, int type, String name) { - final String path = ringtone.getAbsolutePath(); - final String mimeType = name.endsWith(".ogg") ? "audio/ogg" : "audio/mp3"; - ContentValues values = new ContentValues(); - values.put(MediaStore.MediaColumns.DATA, path); - values.put(MediaStore.MediaColumns.TITLE, name); - values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType); - values.put(MediaStore.MediaColumns.SIZE, ringtone.length()); - values.put(MediaStore.Audio.Media.IS_RINGTONE, type == RingtoneManager.TYPE_RINGTONE); - values.put(MediaStore.Audio.Media.IS_NOTIFICATION, - type == RingtoneManager.TYPE_NOTIFICATION); - values.put(MediaStore.Audio.Media.IS_ALARM, type == RingtoneManager.TYPE_ALARM); - values.put(MediaStore.Audio.Media.IS_MUSIC, false); - - Uri uri = MediaStore.Audio.Media.getContentUriForPath(path); - Uri newUri = null; - Cursor c = context.getContentResolver().query(uri, - new String[] {MediaStore.MediaColumns._ID}, - MediaStore.MediaColumns.DATA + "='" + path + "'", - null, null); - if (c != null && c.getCount() > 0) { - c.moveToFirst(); - long id = c.getLong(0); - c.close(); - newUri = Uri.withAppendedPath(Uri.parse(MEDIA_CONTENT_URI), "" + id); - context.getContentResolver().update(uri, values, - MediaStore.MediaColumns._ID + "=" + id, null); - } - if (newUri == null) - newUri = context.getContentResolver().insert(uri, values); - try { - RingtoneManager.setActualDefaultRingtoneUri(context, type, newUri); - } catch (Exception e) { - return false; - } - return true; - } - - public static boolean setDefaultAudible(Context context, int type) { - final String audiblePath = getDefaultAudiblePath(type); - if (audiblePath != null) { - Uri uri = MediaStore.Audio.Media.getContentUriForPath(audiblePath); - Cursor c = context.getContentResolver().query(uri, - new String[] {MediaStore.MediaColumns._ID}, - MediaStore.MediaColumns.DATA + "='" + audiblePath + "'", - null, null); - if (c != null && c.getCount() > 0) { - c.moveToFirst(); - long id = c.getLong(0); - c.close(); - uri = Uri.withAppendedPath( - Uri.parse(MEDIA_CONTENT_URI), "" + id); - } - if (uri != null) - RingtoneManager.setActualDefaultRingtoneUri(context, type, uri); - } else { - return false; - } - return true; - } - - public static String getDefaultAudiblePath(int type) { - final String name; - final String path; - switch (type) { - case RingtoneManager.TYPE_ALARM: - name = SystemProperties.get("ro.config.alarm_alert", null); - path = name != null ? SYSTEM_ALARMS_PATH + File.separator + name : null; - break; - case RingtoneManager.TYPE_NOTIFICATION: - name = SystemProperties.get("ro.config.notification_sound", null); - path = name != null ? SYSTEM_NOTIFICATIONS_PATH + File.separator + name : null; - break; - case RingtoneManager.TYPE_RINGTONE: - name = SystemProperties.get("ro.config.ringtone", null); - path = name != null ? SYSTEM_RINGTONES_PATH + File.separator + name : null; - break; - default: - path = null; - break; - } - return path; - } - - public static void clearAudibles(Context context, String audiblePath) { - final File audibleDir = new File(audiblePath); - if (audibleDir.exists()) { - String[] files = audibleDir.list(); - final ContentResolver resolver = context.getContentResolver(); - for (String s : files) { - final String filePath = audiblePath + File.separator + s; - Uri uri = MediaStore.Audio.Media.getContentUriForPath(filePath); - resolver.delete(uri, MediaStore.MediaColumns.DATA + "=\"" - + filePath + "\"", null); - (new File(filePath)).delete(); - } - } - } - - public static Context createUiContext(final Context context) { - try { - Context uiContext = context.createPackageContext("com.android.systemui", - Context.CONTEXT_RESTRICTED); - return new ThemedUiContext(uiContext, context.getApplicationContext()); - } catch (PackageManager.NameNotFoundException e) { - } - - return null; - } - - public static void registerThemeChangeReceiver(final Context context, - final BroadcastReceiver receiver) { - IntentFilter filter = new IntentFilter(ACTION_THEME_CHANGED); - - context.registerReceiver(receiver, filter); - } - - public static String getLockscreenWallpaperPath(AssetManager assetManager) throws IOException { - String[] assets = assetManager.list(LOCKSCREEN_WALLPAPER_PATH); - String asset = getFirstNonEmptyAsset(assets); - if (asset == null) return null; - return LOCKSCREEN_WALLPAPER_PATH + File.separator + asset; - } - - public static String getWallpaperPath(AssetManager assetManager) throws IOException { - String[] assets = assetManager.list(WALLPAPER_PATH); - String asset = getFirstNonEmptyAsset(assets); - if (asset == null) return null; - return WALLPAPER_PATH + File.separator + asset; - } - - public static List<String> getWallpaperPathList(AssetManager assetManager) - throws IOException { - List<String> wallpaperList = new ArrayList<String>(); - String[] assets = assetManager.list(WALLPAPER_PATH); - for (String asset : assets) { - if (!TextUtils.isEmpty(asset)) { - wallpaperList.add(WALLPAPER_PATH + File.separator + asset); - } - } - return wallpaperList; - } - - // Returns the first non-empty asset name. Empty assets can occur if the APK is built - // with folders included as zip entries in the APK. Searching for files inside "folderName" via - // assetManager.list("folderName") can cause these entries to be included as empty strings. - private static String getFirstNonEmptyAsset(String[] assets) { - if (assets == null) return null; - String filename = null; - for(String asset : assets) { - if (!TextUtils.isEmpty(asset)) { - filename = asset; - break; - } - } - return filename; - } - - public static String getDefaultThemePackageName(Context context) { - final String defaultThemePkg = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.DEFAULT_THEME_PACKAGE); - if (!TextUtils.isEmpty(defaultThemePkg)) { - PackageManager pm = context.getPackageManager(); - try { - if (pm.getPackageInfo(defaultThemePkg, 0) != null) { - return defaultThemePkg; - } - } catch (PackageManager.NameNotFoundException e) { - // doesn't exist so system will be default - Log.w(TAG, "Default theme " + defaultThemePkg + " not found", e); - } - } - - return SYSTEM_DEFAULT; - } - - private static class ThemedUiContext extends ContextWrapper { - private Context mAppContext; - - public ThemedUiContext(Context context, Context appContext) { - super(context); - mAppContext = appContext; - } - - @Override - public Context getApplicationContext() { - return mAppContext; - } - - @Override - public String getPackageName() { - return mAppContext.getPackageName(); - } - } - - // Returns a mutable list of all theme components - public static List<String> getAllComponents() { - List<String> components = new ArrayList<String>(9); - components.add(ThemesColumns.MODIFIES_FONTS); - components.add(ThemesColumns.MODIFIES_LAUNCHER); - components.add(ThemesColumns.MODIFIES_ALARMS); - components.add(ThemesColumns.MODIFIES_BOOT_ANIM); - components.add(ThemesColumns.MODIFIES_ICONS); - components.add(ThemesColumns.MODIFIES_LOCKSCREEN); - components.add(ThemesColumns.MODIFIES_NOTIFICATIONS); - components.add(ThemesColumns.MODIFIES_OVERLAYS); - components.add(ThemesColumns.MODIFIES_RINGTONES); - components.add(ThemesColumns.MODIFIES_STATUS_BAR); - components.add(ThemesColumns.MODIFIES_NAVIGATION_BAR); - components.add(ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN); - return components; - } - - /** - * Returns a mutable list of all the theme components supported by a given package - * NOTE: This queries the themes content provider. If there isn't a provider installed - * or if it is too early in the boot process this method will not work. - */ - public static List<String> getSupportedComponents(Context context, String pkgName) { - List<String> supportedComponents = new ArrayList<String>(); - - String selection = ThemesContract.ThemesColumns.PKG_NAME + "= ?"; - String[] selectionArgs = new String[]{ pkgName }; - Cursor c = context.getContentResolver().query(ThemesContract.ThemesColumns.CONTENT_URI, - null, selection, selectionArgs, null); - - if (c != null) { - if (c.moveToFirst()) { - List<String> allComponents = getAllComponents(); - for (String component : allComponents) { - int index = c.getColumnIndex(component); - if (c.getInt(index) == 1) { - supportedComponents.add(component); - } - } - } - c.close(); - } - return supportedComponents; - } - - /** - * Get the components from the default theme. If the default theme is not SYSTEM then any - * components that are not in the default theme will come from SYSTEM to create a complete - * component map. - * @param context - * @return - */ - public static Map<String, String> getDefaultComponents(Context context) { - String defaultThemePkg = getDefaultThemePackageName(context); - List<String> defaultComponents = null; - List<String> systemComponents = getSupportedComponents(context, SYSTEM_DEFAULT); - if (!SYSTEM_DEFAULT.equals(defaultThemePkg)) { - defaultComponents = getSupportedComponents(context, defaultThemePkg); - } - - Map<String, String> componentMap = new HashMap<String, String>(systemComponents.size()); - if (defaultComponents != null) { - for (String component : defaultComponents) { - componentMap.put(component, defaultThemePkg); - } - } - for (String component : systemComponents) { - if (!componentMap.containsKey(component)) { - componentMap.put(component, SYSTEM_DEFAULT); - } - } - - return componentMap; - } - - /** - * Takes an existing component map and adds any missing components from the default - * map of components. - * @param context - * @param componentMap An existing component map - */ - public static void completeComponentMap(Context context, - Map<String, String> componentMap) { - if (componentMap == null) return; - - Map<String, String> defaultComponents = getDefaultComponents(context); - for (String component : defaultComponents.keySet()) { - if (!componentMap.containsKey(component)) { - componentMap.put(component, defaultComponents.get(component)); - } - } - } - /** * Convenience method to determine if a theme component is a per app theme and not a standard * component. diff --git a/core/java/android/content/res/IThemeProcessingListener.aidl b/core/java/android/content/res/IThemeProcessingListener.aidl deleted file mode 100644 index 2e1c16e..0000000 --- a/core/java/android/content/res/IThemeProcessingListener.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -/** {@hide} */ -oneway interface IThemeProcessingListener { - void onFinishedProcessing(String pkgName); -} diff --git a/core/java/android/content/res/IThemeService.aidl b/core/java/android/content/res/IThemeService.aidl deleted file mode 100644 index 90cb9fb..0000000 --- a/core/java/android/content/res/IThemeService.aidl +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.res.IThemeChangeListener; -import android.content.res.IThemeProcessingListener; -import android.content.res.ThemeChangeRequest; -import android.graphics.Bitmap; - -import java.util.Map; - -/** {@hide} */ -interface IThemeService { - void requestThemeChangeUpdates(in IThemeChangeListener listener); - void removeUpdates(in IThemeChangeListener listener); - - void requestThemeChange(in ThemeChangeRequest request, boolean removePerAppThemes); - void applyDefaultTheme(); - boolean isThemeApplying(); - int getProgress(); - - boolean cacheComposedIcon(in Bitmap icon, String path); - - boolean processThemeResources(String themePkgName); - boolean isThemeBeingProcessed(String themePkgName); - void registerThemeProcessingListener(in IThemeProcessingListener listener); - void unregisterThemeProcessingListener(in IThemeProcessingListener listener); - - void rebuildResourceCache(); -} diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 85ecc0a..6a404e2 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1554,10 +1554,12 @@ public class Resources { * if not already defined in the theme. */ public void applyStyle(int resId, boolean force) { - AssetManager.applyThemeStyle(mTheme, resId, force); + synchronized (mKey) { + AssetManager.applyThemeStyle(mTheme, resId, force); - mThemeResId = resId; - mKey.append(resId, force); + mThemeResId = resId; + mKey.append(resId, force); + } } /** @@ -1570,10 +1572,14 @@ public class Resources { * @param other The existing Theme to copy from. */ public void setTo(Theme other) { - AssetManager.copyTheme(mTheme, other.mTheme); + synchronized (mKey) { + synchronized (other.mKey) { + AssetManager.copyTheme(mTheme, other.mTheme); - mThemeResId = other.mThemeResId; - mKey.setTo(other.getKey()); + mThemeResId = other.mThemeResId; + mKey.setTo(other.getKey()); + } + } } /** @@ -1596,11 +1602,13 @@ public class Resources { * @see #obtainStyledAttributes(AttributeSet, int[], int, int) */ public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) { - final int len = attrs.length; - final TypedArray array = TypedArray.obtain(Resources.this, len); - array.mTheme = this; - AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices); - return array; + synchronized (mKey) { + final int len = attrs.length; + final TypedArray array = TypedArray.obtain(Resources.this, len); + array.mTheme = this; + AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices); + return array; + } } /** @@ -1610,7 +1618,7 @@ public class Resources { * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done * with the array. * - * @param resid The desired style resource. + * @param resId The desired style resource. * @param attrs The desired attributes in the style. * * @throws NotFoundException Throws NotFoundException if the given ID does not exist. @@ -1623,39 +1631,15 @@ public class Resources { * @see #obtainStyledAttributes(int[]) * @see #obtainStyledAttributes(AttributeSet, int[], int, int) */ - public TypedArray obtainStyledAttributes(@StyleRes int resid, @StyleableRes int[] attrs) + public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs) throws NotFoundException { - final int len = attrs.length; - final TypedArray array = TypedArray.obtain(Resources.this, len); - array.mTheme = this; - if (false) { - int[] data = array.mData; - - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("**********************************************************"); - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; i<attrs.length; i++) { - s = s + " 0x" + Integer.toHexString(attrs[i]); - } - System.out.println(s); - s = " Found:"; - TypedValue value = new TypedValue(); - for (i=0; i<attrs.length; i++) { - int d = i*AssetManager.STYLE_NUM_ENTRIES; - value.type = data[d+AssetManager.STYLE_TYPE]; - value.data = data[d+AssetManager.STYLE_DATA]; - value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE]; - value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID]; - s = s + " 0x" + Integer.toHexString(attrs[i]) - + "=" + value; - } - System.out.println(s); + synchronized (mKey) { + final int len = attrs.length; + final TypedArray array = TypedArray.obtain(Resources.this, len); + array.mTheme = this; + AssetManager.applyStyle(mTheme, 0, resId, 0, attrs, array.mData, array.mIndices); + return array; } - AssetManager.applyStyle(mTheme, 0, resid, 0, attrs, array.mData, array.mIndices); - return array; } /** @@ -1708,50 +1692,23 @@ public class Resources { */ public TypedArray obtainStyledAttributes(AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { - final int len = attrs.length; - final TypedArray array = TypedArray.obtain(Resources.this, len); - - // XXX note that for now we only work with compiled XML files. - // To support generic XML files we will need to manually parse - // out the attributes from the XML file (applying type information - // contained in the resources and such). - final XmlBlock.Parser parser = (XmlBlock.Parser)set; - AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes, - parser != null ? parser.mParseState : 0, attrs, array.mData, array.mIndices); + synchronized (mKey) { + final int len = attrs.length; + final TypedArray array = TypedArray.obtain(Resources.this, len); - array.mTheme = this; - array.mXml = parser; + // XXX note that for now we only work with compiled XML files. + // To support generic XML files we will need to manually parse + // out the attributes from the XML file (applying type information + // contained in the resources and such). + final XmlBlock.Parser parser = (XmlBlock.Parser) set; + AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes, + parser != null ? parser.mParseState : 0, + attrs, array.mData, array.mIndices); + array.mTheme = this; + array.mXml = parser; - if (false) { - int[] data = array.mData; - - System.out.println("Attributes:"); - String s = " Attrs:"; - int i; - for (i=0; i<set.getAttributeCount(); i++) { - s = s + " " + set.getAttributeName(i); - int id = set.getAttributeNameResource(i); - if (id != 0) { - s = s + "(0x" + Integer.toHexString(id) + ")"; - } - s = s + "=" + set.getAttributeValue(i); - } - System.out.println(s); - s = " Found:"; - TypedValue value = new TypedValue(); - for (i=0; i<attrs.length; i++) { - int d = i*AssetManager.STYLE_NUM_ENTRIES; - value.type = data[d+AssetManager.STYLE_TYPE]; - value.data = data[d+AssetManager.STYLE_DATA]; - value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE]; - value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID]; - s = s + " 0x" + Integer.toHexString(attrs[i]) - + "=" + value; - } - System.out.println(s); + return array; } - - return array; } /** @@ -1770,18 +1727,20 @@ public class Resources { */ @NonNull public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) { - final int len = attrs.length; - if (values == null || len != values.length) { - throw new IllegalArgumentException( - "Base attribute values must the same length as attrs"); - } + synchronized (mKey) { + final int len = attrs.length; + if (values == null || len != values.length) { + throw new IllegalArgumentException( + "Base attribute values must the same length as attrs"); + } - final TypedArray array = TypedArray.obtain(Resources.this, len); - AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices); - array.mTheme = this; - array.mXml = null; + final TypedArray array = TypedArray.obtain(Resources.this, len); + AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices); + array.mTheme = this; + array.mXml = null; - return array; + return array; + } } /** @@ -1802,14 +1761,9 @@ public class Resources { * <var>outValue</var> is valid, else false. */ public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) { - boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); - if (false) { - System.out.println( - "resolveAttribute #" + Integer.toHexString(resid) - + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) - + ", data=0x" + Integer.toHexString(outValue.data)); + synchronized (mKey) { + return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); } - return got; } /** @@ -1855,8 +1809,11 @@ public class Resources { * @see ActivityInfo */ public int getChangingConfigurations() { - final int nativeChangingConfig = AssetManager.getThemeChangingConfigurations(mTheme); - return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig); + synchronized (mKey) { + final int nativeChangingConfig = + AssetManager.getThemeChangingConfigurations(mTheme); + return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig); + } } /** @@ -1867,7 +1824,9 @@ public class Resources { * @param prefix Text to prefix each line printed. */ public void dump(int priority, String tag, String prefix) { - AssetManager.dumpTheme(mTheme, priority, tag, prefix); + synchronized (mKey) { + AssetManager.dumpTheme(mTheme, priority, tag, prefix); + } } @Override @@ -1917,19 +1876,21 @@ public class Resources { */ @ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true) public String[] getTheme() { - final int N = mKey.mCount; - final String[] themes = new String[N * 2]; - for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { - final int resId = mKey.mResId[j]; - final boolean forced = mKey.mForce[j]; - try { - themes[i] = getResourceName(resId); - } catch (NotFoundException e) { - themes[i] = Integer.toHexString(i); + synchronized (mKey) { + final int N = mKey.mCount; + final String[] themes = new String[N * 2]; + for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) { + final int resId = mKey.mResId[j]; + final boolean forced = mKey.mForce[j]; + try { + themes[i] = getResourceName(resId); + } catch (NotFoundException e) { + themes[i] = Integer.toHexString(i); + } + themes[i + 1] = forced ? "forced" : "not forced"; } - themes[i + 1] = forced ? "forced" : "not forced"; + return themes; } - return themes; } /** @hide */ @@ -1950,13 +1911,15 @@ public class Resources { * @hide */ public void rebase() { - AssetManager.clearTheme(mTheme); - - // Reapply the same styles in the same order. - for (int i = 0; i < mKey.mCount; i++) { - final int resId = mKey.mResId[i]; - final boolean force = mKey.mForce[i]; - AssetManager.applyThemeStyle(mTheme, resId, force); + synchronized (mKey) { + AssetManager.clearTheme(mTheme); + + // Reapply the same styles in the same order. + for (int i = 0; i < mKey.mCount; i++) { + final int resId = mKey.mResId[i]; + final boolean force = mKey.mForce[i]; + AssetManager.applyThemeStyle(mTheme, resId, force); + } } } } diff --git a/core/java/android/content/res/ThemeChangeRequest.aidl b/core/java/android/content/res/ThemeChangeRequest.aidl deleted file mode 100644 index e6cf115..0000000 --- a/core/java/android/content/res/ThemeChangeRequest.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2015 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -/** @hide */ -parcelable ThemeChangeRequest; diff --git a/core/java/android/content/res/ThemeChangeRequest.java b/core/java/android/content/res/ThemeChangeRequest.java deleted file mode 100644 index 1d13bb0..0000000 --- a/core/java/android/content/res/ThemeChangeRequest.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2015 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.pm.ThemeUtils; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - - -import static android.provider.ThemesContract.ThemesColumns.*; - -/** @hide */ -public final class ThemeChangeRequest implements Parcelable { - public static final int DEFAULT_WALLPAPER_ID = -1; - - private final Map<String, String> mThemeComponents = new HashMap<String, String>(); - private final Map<String, String> mPerAppOverlays = new HashMap<String, String>(); - private RequestType mRequestType; - private long mWallpaperId = -1; - - public String getOverlayThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_OVERLAYS); - } - - public String getStatusBarThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_STATUS_BAR); - } - - public String getNavBarThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_NAVIGATION_BAR); - } - - public String getFontThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_FONTS); - } - - public String getIconsThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_ICONS); - } - - public String getBootanimationThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_BOOT_ANIM); - } - - public String getWallpaperThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LAUNCHER); - } - - public String getLockWallpaperThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LOCKSCREEN); - } - - public String getAlarmThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_ALARMS); - } - - public String getNotificationThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_NOTIFICATIONS); - } - - public String getRingtoneThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_RINGTONES); - } - - public String getLiveLockScreenThemePackageName() { - return getThemePackageNameForComponent(MODIFIES_LIVE_LOCK_SCREEN); - } - - public final Map<String, String> getThemeComponentsMap() { - return Collections.unmodifiableMap(mThemeComponents); - } - - public long getWallpaperId() { - return mWallpaperId; - } - - /** - * Get the mapping for per app themes - * @return A mapping of apps and the theme to apply for each one. or null if none set. - */ - public final Map<String, String> getPerAppOverlays() { - return Collections.unmodifiableMap(mPerAppOverlays); - } - - public int getNumChangesRequested() { - return mThemeComponents.size() + mPerAppOverlays.size(); - } - - public RequestType getReqeustType() { - return mRequestType; - } - - private String getThemePackageNameForComponent(String componentName) { - return mThemeComponents.get(componentName); - } - - private ThemeChangeRequest(Map<String, String> components, Map<String, String> perAppThemes, - RequestType requestType, long wallpaperId) { - if (components != null) { - mThemeComponents.putAll(components); - } - if (perAppThemes != null) { - mPerAppOverlays.putAll(perAppThemes); - } - mRequestType = requestType; - mWallpaperId = wallpaperId; - } - - private ThemeChangeRequest(Parcel source) { - int numComponents = source.readInt(); - for (int i = 0; i < numComponents; i++) { - mThemeComponents.put(source.readString(), source.readString()); - } - - numComponents = source.readInt(); - for (int i = 0 ; i < numComponents; i++) { - mPerAppOverlays.put(source.readString(), source.readString()); - } - mRequestType = RequestType.values()[source.readInt()]; - mWallpaperId = source.readLong(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mThemeComponents.size()); - for (String component : mThemeComponents.keySet()) { - dest.writeString(component); - dest.writeString(mThemeComponents.get(component)); - } - dest.writeInt((mPerAppOverlays.size())); - for (String appPkgName : mPerAppOverlays.keySet()) { - dest.writeString(appPkgName); - dest.writeString(mPerAppOverlays.get(appPkgName)); - } - dest.writeInt(mRequestType.ordinal()); - dest.writeLong(mWallpaperId); - } - - public static final Parcelable.Creator<ThemeChangeRequest> CREATOR = - new Parcelable.Creator<ThemeChangeRequest>() { - @Override - public ThemeChangeRequest createFromParcel(Parcel source) { - return new ThemeChangeRequest(source); - } - - @Override - public ThemeChangeRequest[] newArray(int size) { - return new ThemeChangeRequest[size]; - } - }; - - public enum RequestType { - USER_REQUEST, - USER_REQUEST_MIXNMATCH, - THEME_UPDATED, - THEME_REMOVED, - THEME_RESET; - } - - public static class Builder { - Map<String, String> mThemeComponents = new HashMap<String, String>(); - Map<String, String> mPerAppOverlays = new HashMap<String, String>(); - RequestType mRequestType = RequestType.USER_REQUEST; - long mWallpaperId; - - public Builder() {} - - public Builder(ThemeConfig themeConfig) { - if (themeConfig != null) { - buildChangeRequestFromThemeConfig(themeConfig); - } - } - - public Builder setOverlay(String pkgName) { - return setComponent(MODIFIES_OVERLAYS, pkgName); - } - - public Builder setStatusBar(String pkgName) { - return setComponent(MODIFIES_STATUS_BAR, pkgName); - } - - public Builder setNavBar(String pkgName) { - return setComponent(MODIFIES_NAVIGATION_BAR, pkgName); - } - - public Builder setFont(String pkgName) { - return setComponent(MODIFIES_FONTS, pkgName); - } - - public Builder setIcons(String pkgName) { - return setComponent(MODIFIES_ICONS, pkgName); - } - - public Builder setBootanimation(String pkgName) { - return setComponent(MODIFIES_BOOT_ANIM, pkgName); - } - - public Builder setWallpaper(String pkgName) { - return setComponent(MODIFIES_LAUNCHER, pkgName); - } - - // Used in the case that more than one wallpaper exists for a given pkg name - public Builder setWallpaperId(long id) { - mWallpaperId = id; - return this; - } - - public Builder setLockWallpaper(String pkgName) { - return setComponent(MODIFIES_LOCKSCREEN, pkgName); - } - - public Builder setAlarm(String pkgName) { - return setComponent(MODIFIES_ALARMS, pkgName); - } - - public Builder setNotification(String pkgName) { - return setComponent(MODIFIES_NOTIFICATIONS, pkgName); - } - - public Builder setRingtone(String pkgName) { - return setComponent(MODIFIES_RINGTONES, pkgName); - } - - public Builder setLiveLockScreen(String pkgName) { - return setComponent(MODIFIES_LIVE_LOCK_SCREEN, pkgName); - } - - public Builder setComponent(String component, String pkgName) { - if (pkgName != null) { - mThemeComponents.put(component, pkgName); - } else { - mThemeComponents.remove(component); - } - return this; - } - - public Builder setAppOverlay(String appPkgName, String themePkgName) { - if (appPkgName != null) { - if (themePkgName != null) { - mPerAppOverlays.put(appPkgName, themePkgName); - } else { - mPerAppOverlays.remove(appPkgName); - } - } - - return this; - } - - public Builder setRequestType(RequestType requestType) { - mRequestType = requestType != null ? requestType : RequestType.USER_REQUEST; - return this; - } - - public ThemeChangeRequest build() { - return new ThemeChangeRequest(mThemeComponents, mPerAppOverlays, - mRequestType, mWallpaperId); - } - - private void buildChangeRequestFromThemeConfig(ThemeConfig themeConfig) { - if (themeConfig.getFontPkgName() != null) { - this.setFont(themeConfig.getFontPkgName()); - } - if (themeConfig.getIconPackPkgName() != null) { - this.setIcons(themeConfig.getIconPackPkgName()); - } - if (themeConfig.getOverlayPkgName() != null) { - this.setOverlay(themeConfig.getOverlayPkgName()); - } - if (themeConfig.getOverlayForStatusBar() != null) { - this.setStatusBar(themeConfig.getOverlayForStatusBar()); - } - if (themeConfig.getOverlayForNavBar() != null) { - this.setNavBar(themeConfig.getOverlayForNavBar()); - } - - // Check if there are any per-app overlays using this theme - final Map<String, ThemeConfig.AppTheme> themes = themeConfig.getAppThemes(); - for (String appPkgName : themes.keySet()) { - if (ThemeUtils.isPerAppThemeComponent(appPkgName)) { - this.setAppOverlay(appPkgName, themes.get(appPkgName).getOverlayPkgName()); - } - } - } - } -} diff --git a/core/java/android/content/res/ThemeConfig.java b/core/java/android/content/res/ThemeConfig.java index ac95d6b..f304801 100644 --- a/core/java/android/content/res/ThemeConfig.java +++ b/core/java/android/content/res/ThemeConfig.java @@ -1,12 +1,12 @@ /* - * Copyright (C) 2014 The CyanogenMod Project + * Copyright (C) 2016 The CyanogenMod Project * Portions copyright (C) 2014, T-Mobile USA, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -17,12 +17,13 @@ package android.content.res; import android.content.ContentResolver; -import android.content.res.ThemeChangeRequest.RequestType; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.JsonReader; import android.util.JsonToken; import android.util.JsonWriter; @@ -34,8 +35,6 @@ import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.Map; /** @@ -61,9 +60,7 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi private static final SystemAppTheme mSystemAppTheme = new SystemAppTheme(); // Maps pkgname to theme (ex com.angry.birds -> red theme) - protected final Map<String, AppTheme> mThemes = new HashMap<String, AppTheme>(); - - private RequestType mLastThemeChangeRequestType = RequestType.USER_REQUEST; + protected final Map<String, AppTheme> mThemes = new ArrayMap<>(); public ThemeConfig(Map<String, AppTheme> appThemes) { mThemes.putAll(appThemes); @@ -111,10 +108,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi return Collections.unmodifiableMap(mThemes); } - public RequestType getLastThemeChangeRequestType() { - return mLastThemeChangeRequestType; - } - private AppTheme getThemeFor(String pkgName) { AppTheme theme = mThemes.get(pkgName); if (theme == null) theme = getDefaultTheme(); @@ -136,12 +129,11 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi ThemeConfig o = (ThemeConfig) object; Map<String, AppTheme> currThemes = (mThemes == null) ? - new HashMap<String, AppTheme>() : mThemes; + new ArrayMap<String, AppTheme>() : mThemes; Map<String, AppTheme> newThemes = (o.mThemes == null) ? - new HashMap<String, AppTheme>() : o.mThemes; + new ArrayMap<String, AppTheme>() : o.mThemes; - return (currThemes.equals(newThemes) && - mLastThemeChangeRequestType == o.mLastThemeChangeRequestType); + return currThemes.equals(newThemes); } return false; } @@ -160,8 +152,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public int hashCode() { int hash = 17; hash = 31 * hash + mThemes.hashCode(); - hash = 31 * hash + (mLastThemeChangeRequestType == null ? 0 : - mLastThemeChangeRequestType.ordinal()); return hash; } @@ -227,7 +217,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public void writeToParcel(Parcel dest, int flags) { String json = JsonSerializer.toJson(this); dest.writeString(json); - dest.writeInt(mLastThemeChangeRequestType.ordinal()); } public static final Parcelable.Creator<ThemeConfig> CREATOR = @@ -235,7 +224,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public ThemeConfig createFromParcel(Parcel source) { String json = source.readString(); ThemeConfig themeConfig = JsonSerializer.fromJson(json); - themeConfig.mLastThemeChangeRequestType = RequestType.values()[source.readInt()]; return themeConfig; } @@ -351,10 +339,9 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public static class Builder { - private HashMap<String, String> mOverlays = new HashMap<String, String>(); - private HashMap<String, String> mIcons = new HashMap<String, String>(); - private HashMap<String, String> mFonts = new HashMap<String, String>(); - private RequestType mLastThemeChangeRequestType = RequestType.USER_REQUEST; + private Map<String, String> mOverlays = new ArrayMap<>(); + private Map<String, String> mIcons = new ArrayMap<>(); + private Map<String, String> mFonts = new ArrayMap<>(); public Builder() {} @@ -366,7 +353,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi mIcons.put(key, appTheme.getIconPackPkgName()); mOverlays.put(key, appTheme.getOverlayPkgName()); } - mLastThemeChangeRequestType = theme.mLastThemeChangeRequestType; } /** @@ -427,18 +413,13 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi return this; } - public Builder setLastThemeChangeRequestType(RequestType requestType) { - mLastThemeChangeRequestType = requestType; - return this; - } - public ThemeConfig build() { - HashSet<String> appPkgSet = new HashSet<String>(); + ArraySet<String> appPkgSet = new ArraySet<>(); appPkgSet.addAll(mOverlays.keySet()); appPkgSet.addAll(mIcons.keySet()); appPkgSet.addAll(mFonts.keySet()); - HashMap<String, AppTheme> appThemes = new HashMap<String, AppTheme>(); + Map<String, AppTheme> appThemes = new ArrayMap<>(); for(String appPkgName : appPkgSet) { String icon = mIcons.get(appPkgName); String overlay = mOverlays.get(appPkgName); @@ -455,7 +436,6 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi } } ThemeConfig themeConfig = new ThemeConfig(appThemes); - themeConfig.mLastThemeChangeRequestType = mLastThemeChangeRequestType; return themeConfig; } } @@ -506,7 +486,7 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public static ThemeConfig fromJson(String json) { if (json == null) return null; - HashMap<String, AppTheme> map = new HashMap<String, AppTheme>(); + Map<String, AppTheme> map = new ArrayMap<>(); StringReader reader = null; JsonReader jsonReader = null; try { @@ -582,7 +562,7 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi public static class SystemConfig extends ThemeConfig { public SystemConfig() { - super(new HashMap<String, AppTheme>()); + super(new ArrayMap<String, AppTheme>()); } } @@ -593,7 +573,7 @@ public class ThemeConfig implements Cloneable, Parcelable, Comparable<ThemeConfi @Override public String toString() { - return "No Theme Applied (Holo)"; + return "No Theme Applied (System)"; } } } diff --git a/core/java/android/content/res/ThemeManager.java b/core/java/android/content/res/ThemeManager.java deleted file mode 100644 index fd05f1e..0000000 --- a/core/java/android/content/res/ThemeManager.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.content.res; - -import android.content.Context; -import android.content.pm.ThemeUtils; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * {@hide} - */ -public class ThemeManager { - private static final String TAG = ThemeManager.class.getName(); - private Context mContext; - private IThemeService mService; - private Handler mHandler; - - private Set<ThemeChangeListener> mChangeListeners = - new HashSet<ThemeChangeListener>(); - - private Set<ThemeProcessingListener> mProcessingListeners = - new HashSet<ThemeProcessingListener>(); - - public ThemeManager(Context context, IThemeService service) { - mContext = context; - mService = service; - mHandler = new Handler(Looper.getMainLooper()); - } - - private final IThemeChangeListener mThemeChangeListener = new IThemeChangeListener.Stub() { - @Override - public void onProgress(final int progress) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mChangeListeners) { - List<ThemeChangeListener> listenersToRemove = new ArrayList - <ThemeChangeListener>(); - for (ThemeChangeListener listener : mChangeListeners) { - try { - listener.onProgress(progress); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change progress", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeChangeListener listener : listenersToRemove) { - mChangeListeners.remove(listener); - } - } - } - } - }); - } - - @Override - public void onFinish(final boolean isSuccess) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mChangeListeners) { - List<ThemeChangeListener> listenersToRemove = new ArrayList - <ThemeChangeListener>(); - for (ThemeChangeListener listener : mChangeListeners) { - try { - listener.onFinish(isSuccess); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change listener", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeChangeListener listener : listenersToRemove) { - mChangeListeners.remove(listener); - } - } - } - } - }); - } - }; - - private final IThemeProcessingListener mThemeProcessingListener = - new IThemeProcessingListener.Stub() { - @Override - public void onFinishedProcessing(final String pkgName) throws RemoteException { - mHandler.post(new Runnable() { - @Override - public void run() { - synchronized (mProcessingListeners) { - List<ThemeProcessingListener> listenersToRemove = new ArrayList - <ThemeProcessingListener>(); - for (ThemeProcessingListener listener : mProcessingListeners) { - try { - listener.onFinishedProcessing(pkgName); - } catch (Throwable e) { - Log.w(TAG, "Unable to update theme change progress", e); - listenersToRemove.add(listener); - } - } - if (listenersToRemove.size() > 0) { - for (ThemeProcessingListener listener : listenersToRemove) { - mProcessingListeners.remove(listener); - } - } - } - } - }); - } - }; - - - public void addClient(ThemeChangeListener listener) { - synchronized (mChangeListeners) { - if (mChangeListeners.contains(listener)) { - throw new IllegalArgumentException("Client was already added "); - } - if (mChangeListeners.size() == 0) { - try { - mService.requestThemeChangeUpdates(mThemeChangeListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to register listener", e); - } - } - mChangeListeners.add(listener); - } - } - - public void removeClient(ThemeChangeListener listener) { - synchronized (mChangeListeners) { - mChangeListeners.remove(listener); - if (mChangeListeners.size() == 0) { - try { - mService.removeUpdates(mThemeChangeListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to remove listener", e); - } - } - } - } - - public void onClientPaused(ThemeChangeListener listener) { - removeClient(listener); - } - - public void onClientResumed(ThemeChangeListener listener) { - addClient(listener); - } - - public void onClientDestroyed(ThemeChangeListener listener) { - removeClient(listener); - } - - /** - * Register a ThemeProcessingListener to be notified when a theme is done being processed. - * @param listener ThemeChangeListener to register - */ - public void registerProcessingListener(ThemeProcessingListener listener) { - synchronized (mProcessingListeners) { - if (mProcessingListeners.contains(listener)) { - throw new IllegalArgumentException("Listener was already added "); - } - if (mProcessingListeners.size() == 0) { - try { - mService.registerThemeProcessingListener(mThemeProcessingListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to register listener", e); - } - } - mProcessingListeners.add(listener); - } - } - - /** - * Unregister a ThemeChangeListener. - * @param listener ThemeChangeListener to unregister - */ - public void unregisterProcessingListener(ThemeChangeListener listener) { - synchronized (mProcessingListeners) { - mProcessingListeners.remove(listener); - if (mProcessingListeners.size() == 0) { - try { - mService.unregisterThemeProcessingListener(mThemeProcessingListener); - } catch (RemoteException e) { - Log.w(TAG, "Unable to remove listener", e); - } - } - } - } - - /** - * Convenience method. Applies the entire theme. - */ - public void requestThemeChange(String pkgName) { - //List<String> components = ThemeUtils.getSupportedComponents(mContext, pkgName); - //requestThemeChange(pkgName, components); - } - - public void requestThemeChange(String pkgName, List<String> components) { - requestThemeChange(pkgName, components, true); - } - - public void requestThemeChange(String pkgName, List<String> components, - boolean removePerAppThemes) { - Map<String, String> componentMap = new HashMap<String, String>(components.size()); - for (String component : components) { - componentMap.put(component, pkgName); - } - requestThemeChange(componentMap, removePerAppThemes); - } - - public void requestThemeChange(Map<String, String> componentMap) { - requestThemeChange(componentMap, true); - } - - public void requestThemeChange(Map<String, String> componentMap, boolean removePerAppThemes) { - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for (String component : componentMap.keySet()) { - builder.setComponent(component, componentMap.get(component)); - } - - requestThemeChange(builder.build(), removePerAppThemes); - } - - public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) { - try { - mService.requestThemeChange(request, removePerAppThemes); - } catch (RemoteException e) { - logThemeServiceException(e); - } - } - - public void applyDefaultTheme() { - try { - mService.applyDefaultTheme(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - } - - public boolean isThemeApplying() { - try { - return mService.isThemeApplying(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - - return false; - } - - public boolean isThemeBeingProcessed(String themePkgName) { - try { - return mService.isThemeBeingProcessed(themePkgName); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return false; - } - - public int getProgress() { - try { - return mService.getProgress(); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return -1; - } - - public boolean processThemeResources(String themePkgName) { - try { - return mService.processThemeResources(themePkgName); - } catch (RemoteException e) { - logThemeServiceException(e); - } - return false; - } - - private void logThemeServiceException(Exception e) { - Log.w(TAG, "Unable to access ThemeService", e); - } - - public interface ThemeChangeListener { - void onProgress(int progress); - void onFinish(boolean isSuccess); - } - - public interface ThemeProcessingListener { - void onFinishedProcessing(String pkgName); - } -} - diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index dc576a5..dd15d38 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -40,6 +40,7 @@ import android.util.Log; import android.text.TextUtils; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.SystemProperties; import java.io.IOException; import java.lang.ref.WeakReference; @@ -483,8 +484,21 @@ public class Camera { mEventHandler = null; } - return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, - ActivityThread.currentOpPackageName()); + String packageName = ActivityThread.currentOpPackageName(); + + //Force HAL1 if the package name falls in this bucket + String packageList = SystemProperties.get("camera.hal1.packagelist", ""); + if (packageList.length() > 0) { + TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(','); + splitter.setString(packageList); + for (String str : splitter) { + if (packageName.equals(str)) { + halVersion = CAMERA_HAL_API_VERSION_1_0; + break; + } + } + } + return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, packageName); } private int cameraInitNormal(int cameraId) { @@ -3471,8 +3485,8 @@ public class Camera { } /** - * Sets GPS processing method. It will store up to 32 characters - * in JPEG EXIF header. + * Sets GPS processing method. The method will be stored in a UTF-8 string up to 31 bytes + * long, in the JPEG EXIF header. * * @param processing_method The processing method to get this location. */ diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index a2ef078..7464211 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -398,17 +398,24 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * this camera device.</p> * <p>For devices at the LEGACY level or above:</p> * <ul> - * <li>This list will always include (30, 30).</li> - * <li>Also, for constant-framerate recording, for each normal + * <li> + * <p>For constant-framerate recording, for each normal + * {@link android.media.CamcorderProfile CamcorderProfile}, that is, a * {@link android.media.CamcorderProfile CamcorderProfile} that has * {@link android.media.CamcorderProfile#quality quality} in * the range [{@link android.media.CamcorderProfile#QUALITY_LOW QUALITY_LOW}, * {@link android.media.CamcorderProfile#QUALITY_2160P QUALITY_2160P}], if the profile is * supported by the device and has * {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} <code>x</code>, this list will - * always include (<code>x</code>,<code>x</code>).</li> - * <li>For preview streaming use case, this list will always include (<code>min</code>, <code>max</code>) where - * <code>min</code> <= 15 and <code>max</code> >= 30.</li> + * always include (<code>x</code>,<code>x</code>).</p> + * </li> + * <li> + * <p>Also, a camera device must either not support any + * {@link android.media.CamcorderProfile CamcorderProfile}, + * or support at least one + * normal {@link android.media.CamcorderProfile CamcorderProfile} that has + * {@link android.media.CamcorderProfile#videoFrameRate videoFrameRate} <code>x</code> >= 24.</p> + * </li> * </ul> * <p>For devices at the LIMITED level or above:</p> * <ul> diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 35a1d96..f61892e 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -472,13 +472,13 @@ public abstract class CameraMetadata<TKey> { * <li>The maximum available resolution for RAW_SENSOR streams * will match either the value in * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} or - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</li> + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}.</li> * <li>All DNG-related optional metadata entries are provided * by the camera device.</li> * </ul> * - * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES */ public static final int REQUEST_AVAILABLE_CAPABILITIES_RAW = 3; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index 3f566eb..67835a0 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -556,6 +556,10 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * Set a capture request field to a value. The field definitions can be * found in {@link CaptureRequest}. * + * <p>Setting a field to {@code null} will remove that field from the capture request. + * Unless the field is optional, removing it will likely produce an error from the camera + * device when the request is submitted.</p> + * * @param key The metadata field to write. * @param value The value to set the field to, which must be of a matching * type to the key. diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 7f5f377..9e639e8 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -48,6 +48,9 @@ interface INetworkPolicyManager { /** Snooze limit on policy matching given template. */ void snoozeLimit(in NetworkTemplate template); + /** Snooze warning on policy matching given template. */ + void snoozeWarning(in NetworkTemplate template); + /** Control if background data is restricted system-wide. */ void setRestrictBackground(boolean restrictBackground); boolean getRestrictBackground(); diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index a83e722..eab22b8 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.GET_SIGNATURES; import static android.net.NetworkPolicy.CYCLE_NONE; import static android.text.format.Time.MONTH_DAY; +import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -81,6 +82,54 @@ public class NetworkPolicyManager { */ public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; + /** + * Broadcast intent action for informing a custom component about a network policy + * notification. + * @hide + */ + @SystemApi + public static final String ACTION_SHOW_NETWORK_POLICY_NOTIFICATION = + "android.net.action.SHOW_NETWORK_POLICY_NOTIFICATION"; + + /** + * The sequence number associated with the notification - a higher number + * indicates previous notifications may be disregarded. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_SEQUENCE_NUMBER = + "android.net.extra.NOTIFICATION_SEQUENCE_NUMBER"; + + /** + * The type of notification that should be presented to the user. + * @hide + */ + @SystemApi + public static final String EXTRA_NOTIFICATION_TYPE = "android.net.extra.NOTIFICATION_TYPE"; + + @SystemApi + public static final int NOTIFICATION_TYPE_NONE = 0; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_WARNING = 1; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_REACHED_LIMIT = 2; + @SystemApi + public static final int NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT = 3; + + /** + * The number of bytes used on the network in the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_BYTES_USED = "android.net.extra.BYTES_USED"; + + /** + * The network policy for the network in the notification. + * @hide + */ + @SystemApi + public static final String EXTRA_NETWORK_POLICY = "android.net.extra.NETWORK_POLICY"; + private final Context mContext; private INetworkPolicyManager mService; diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java index 29daf35..5880e5d 100644 --- a/core/java/android/net/NetworkScorerAppManager.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -33,6 +33,7 @@ import android.util.Log; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -90,8 +91,13 @@ public final class NetworkScorerAppManager { * @return the list of scorers, or the empty list if there are no valid scorers. */ public static Collection<NetworkScorerAppData> getAllValidScorers(Context context) { - List<NetworkScorerAppData> scorers = new ArrayList<>(); + // Network scorer apps can only run as the primary user so exit early if we're not the + // primary user. + if (UserHandle.getCallingUserId() != 0 /*USER_SYSTEM*/) { + return Collections.emptyList(); + } + List<NetworkScorerAppData> scorers = new ArrayList<>(); PackageManager pm = context.getPackageManager(); // Only apps installed under the primary user of the device can be scorers. List<ResolveInfo> receivers = @@ -104,8 +110,9 @@ public final class NetworkScorerAppManager { continue; } if (!permission.BROADCAST_NETWORK_PRIVILEGED.equals(receiverInfo.permission)) { - // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which means - // anyone could trigger network scoring and flood the framework with score requests. + // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which + // means anyone could trigger network scoring and flood the framework with score + // requests. continue; } if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) != @@ -127,8 +134,8 @@ public final class NetworkScorerAppManager { } } - // NOTE: loadLabel will attempt to load the receiver's label and fall back to the app - // label if none is present. + // NOTE: loadLabel will attempt to load the receiver's label and fall back to the + // app label if none is present. scorers.add(new NetworkScorerAppData(receiverInfo.packageName, receiverInfo.applicationInfo.uid, receiverInfo.loadLabel(pm), configurationActivityClassName)); diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index d619c0a..c7d4c65 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -371,40 +371,44 @@ public final class NfcActivityManager extends IAppCallback.Stub flags = state.flags; activity = state.activity; } - - // Make callbacks without lock - if (ndefCallback != null) { - message = ndefCallback.createNdefMessage(event); - } - if (urisCallback != null) { - uris = urisCallback.createBeamUris(event); - if (uris != null) { - ArrayList<Uri> validUris = new ArrayList<Uri>(); - for (Uri uri : uris) { - if (uri == null) { - Log.e(TAG, "Uri not allowed to be null."); - continue; - } - String scheme = uri.getScheme(); - if (scheme == null || (!scheme.equalsIgnoreCase("file") && - !scheme.equalsIgnoreCase("content"))) { - Log.e(TAG, "Uri needs to have " + - "either scheme file or scheme content"); - continue; + final long ident = Binder.clearCallingIdentity(); + try { + // Make callbacks without lock + if (ndefCallback != null) { + message = ndefCallback.createNdefMessage(event); + } + if (urisCallback != null) { + uris = urisCallback.createBeamUris(event); + if (uris != null) { + ArrayList<Uri> validUris = new ArrayList<Uri>(); + for (Uri uri : uris) { + if (uri == null) { + Log.e(TAG, "Uri not allowed to be null."); + continue; + } + String scheme = uri.getScheme(); + if (scheme == null || (!scheme.equalsIgnoreCase("file") && + !scheme.equalsIgnoreCase("content"))) { + Log.e(TAG, "Uri needs to have " + + "either scheme file or scheme content"); + continue; + } + uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); + validUris.add(uri); } - uri = ContentProvider.maybeAddUserId(uri, UserHandle.myUserId()); - validUris.add(uri); - } - uris = validUris.toArray(new Uri[validUris.size()]); + uris = validUris.toArray(new Uri[validUris.size()]); + } } - } - if (uris != null && uris.length > 0) { - for (Uri uri : uris) { - // Grant the NFC process permission to read these URIs - activity.grantUriPermission("com.android.nfc", uri, - Intent.FLAG_GRANT_READ_URI_PERMISSION); + if (uris != null && uris.length > 0) { + for (Uri uri : uris) { + // Grant the NFC process permission to read these URIs + activity.grantUriPermission("com.android.nfc", uri, + Intent.FLAG_GRANT_READ_URI_PERMISSION); + } } + } finally { + Binder.restoreCallingIdentity(ident); } return new BeamShareData(message, uris, new UserHandle(UserHandle.myUserId()), flags); } diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index 1f3e9a7..050820c 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +17,7 @@ package android.os; +import android.app.IBatteryService; import android.content.Context; import android.os.BatteryProperty; import android.os.IBatteryPropertiesRegistrar; @@ -95,6 +97,79 @@ public class BatteryManager { /** * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock status constant. + * @hide + */ + public static final String EXTRA_DOCK_STATUS = "dock_status"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock health constant. + * @hide + */ + public static final String EXTRA_DOCK_HEALTH = "dock_health"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * boolean indicating whether a dock battery is present. + * @hide + */ + public static final String EXTRA_DOCK_PRESENT = "dock_present"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer field containing the current dock battery level, from 0 to + * {@link #EXTRA_SCALE}. + * @hide + */ + public static final String EXTRA_DOCK_LEVEL = "dock_level"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the maximum dock battery level. + * @hide + */ + public static final String EXTRA_DOCK_SCALE = "dock_scale"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the resource ID of a small status bar icon + * indicating the current dock battery state. + * @hide + */ + public static final String EXTRA_DOCK_ICON_SMALL = "dock_icon-small"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer indicating whether the device is plugged in to a dock power + * source. + * @hide + */ + public static final String EXTRA_DOCK_PLUGGED = "dock_plugged"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock battery voltage level. + * @hide + */ + public static final String EXTRA_DOCK_VOLTAGE = "dock_voltage"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * integer containing the current dock battery temperature. + * @hide + */ + public static final String EXTRA_DOCK_TEMPERATURE = "dock_temperature"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: + * String describing the technology of the current dock battery. + * @hide + */ + public static final String EXTRA_DOCK_TECHNOLOGY = "dock_technology"; + + /** + * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}: * Int value set to nonzero if an unsupported charger is attached * to the device. * {@hide} @@ -133,10 +208,23 @@ public class BatteryManager { /** Power source is wireless. */ public static final int BATTERY_PLUGGED_WIRELESS = 4; + // values of the "dock_plugged" field in the ACTION_BATTERY_CHANGED intent. + // These must be powers of 2. + /** Power source is an DockAC charger. + * @hide*/ + public static final int BATTERY_DOCK_PLUGGED_AC = 1; + /** Power source is an DockUSB charger. + * @hide*/ + public static final int BATTERY_DOCK_PLUGGED_USB = 2; + /** @hide */ public static final int BATTERY_PLUGGED_ANY = BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS; + /** @hide */ + public static final int BATTERY_DOCK_PLUGGED_ANY = + BATTERY_DOCK_PLUGGED_AC | BATTERY_DOCK_PLUGGED_USB; + /** * Sent when the device's battery has started charging (or has reached full charge * and the device is on power). This is a good time to do work that you would like to @@ -191,6 +279,7 @@ public class BatteryManager { */ public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5; + private final IBatteryService mBatteryService; private final IBatteryStats mBatteryStats; private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar; @@ -202,6 +291,27 @@ public class BatteryManager { ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface( ServiceManager.getService("batteryproperties")); + mBatteryService = null; + } + + /** @hide */ + public BatteryManager(IBatteryService service) { + super(); + mBatteryStats = IBatteryStats.Stub.asInterface( + ServiceManager.getService(BatteryStats.SERVICE_NAME)); + mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface( + ServiceManager.getService("batteryproperties")); + mBatteryService = service; + } + + /** @hide */ + public boolean isDockBatterySupported() { + try { + return mBatteryService != null && mBatteryService.isDockBatterySupported(); + } catch (RemoteException ex) { + // Ignore + } + return false; } /** @@ -223,8 +333,10 @@ public class BatteryManager { * * Returns the requested value, or Long.MIN_VALUE if property not * supported on this system or on other error. + * fromDock determines if the property is query from the normal battery + * or the dock battery. */ - private long queryProperty(int id) { + private long queryProperty(int id, boolean fromDock) { long ret; if (mBatteryPropertiesRegistrar == null) { @@ -234,7 +346,13 @@ public class BatteryManager { try { BatteryProperty prop = new BatteryProperty(); - if (mBatteryPropertiesRegistrar.getProperty(id, prop) == 0) + final int callResult; + if (!fromDock) { + callResult = mBatteryPropertiesRegistrar.getProperty(id, prop); + } else { + callResult = mBatteryPropertiesRegistrar.getDockProperty(id, prop); + } + if (callResult == 0) ret = prop.getLong(); else ret = Long.MIN_VALUE; @@ -255,7 +373,7 @@ public class BatteryManager { * @return the property value, or Integer.MIN_VALUE if not supported. */ public int getIntProperty(int id) { - return (int)queryProperty(id); + return (int)queryProperty(id, false); } /** @@ -268,6 +386,40 @@ public class BatteryManager { * @return the property value, or Long.MIN_VALUE if not supported. */ public long getLongProperty(int id) { - return queryProperty(id); + return queryProperty(id, false); + } + + /** + * Return the value of a dock battery property of integer type. If the + * platform does not provide the property queried, this value will + * be Integer.MIN_VALUE. + * + * @param id identifier of the requested property + * + * @return the property value, or Integer.MIN_VALUE if not supported. + * @hide + */ + public int getIntDockProperty(int id) { + if (!isDockBatterySupported()) { + return Integer.MIN_VALUE; + } + return (int)queryProperty(id, true); + } + + /** + * Return the value of a dock battery property of long type If the + * platform does not provide the property queried, this value will + * be Long.MIN_VALUE. + * + * @param id identifier of the requested property + * + * @return the property value, or Long.MIN_VALUE if not supported. + * @hide + */ + public long getLongDockProperty(int id) { + if (!isDockBatterySupported()) { + return Long.MIN_VALUE; + } + return queryProperty(id, true); } } diff --git a/core/java/android/os/BatteryManagerInternal.java b/core/java/android/os/BatteryManagerInternal.java index f3a95b9..1abb3d5 100644 --- a/core/java/android/os/BatteryManagerInternal.java +++ b/core/java/android/os/BatteryManagerInternal.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +44,26 @@ public abstract class BatteryManagerInternal { public abstract boolean getBatteryLevelLow(); /** + * Returns whether dock batteries is supported + */ + public abstract boolean isDockBatterySupported(); + + /** + * Returns the current dock plug type. + */ + public abstract int getDockPlugType(); + + /** + * Returns dock battery level as a percentage. + */ + public abstract int getDockBatteryLevel(); + + /** + * Returns whether we currently consider the dock battery level to be low. + */ + public abstract boolean getDockBatteryLevelLow(); + + /** * Returns a non-zero value if an unsupported charger is attached. */ public abstract int getInvalidCharger(); diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java index 29e868c..cad741a 100644 --- a/core/java/android/os/BatteryProperties.java +++ b/core/java/android/os/BatteryProperties.java @@ -1,4 +1,5 @@ /* Copyright 2013, The Android Open Source Project + * Copyright 2016, The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +32,16 @@ public class BatteryProperties implements Parcelable { public int batteryTemperature; public String batteryTechnology; + public boolean dockBatterySupported; + public boolean chargerDockAcOnline; + public int dockBatteryStatus; + public int dockBatteryHealth; + public boolean dockBatteryPresent; + public int dockBatteryLevel; + public int dockBatteryVoltage; + public int dockBatteryTemperature; + public String dockBatteryTechnology; + public BatteryProperties() { } @@ -46,6 +57,16 @@ public class BatteryProperties implements Parcelable { batteryVoltage = other.batteryVoltage; batteryTemperature = other.batteryTemperature; batteryTechnology = other.batteryTechnology; + + dockBatterySupported = other.dockBatterySupported; + chargerDockAcOnline = other.chargerDockAcOnline; + dockBatteryStatus = other.dockBatteryStatus; + dockBatteryHealth = other.dockBatteryHealth; + dockBatteryPresent = other.dockBatteryPresent; + dockBatteryLevel = other.dockBatteryLevel; + dockBatteryVoltage = other.dockBatteryVoltage; + dockBatteryTemperature = other.dockBatteryTemperature; + dockBatteryTechnology = other.dockBatteryTechnology; } /* @@ -65,6 +86,27 @@ public class BatteryProperties implements Parcelable { batteryVoltage = p.readInt(); batteryTemperature = p.readInt(); batteryTechnology = p.readString(); + + dockBatterySupported = p.readInt() == 1 ? true : false; + if (dockBatterySupported) { + chargerDockAcOnline = p.readInt() == 1 ? true : false; + dockBatteryStatus = p.readInt(); + dockBatteryHealth = p.readInt(); + dockBatteryPresent = p.readInt() == 1 ? true : false; + dockBatteryLevel = p.readInt(); + dockBatteryVoltage = p.readInt(); + dockBatteryTemperature = p.readInt(); + dockBatteryTechnology = p.readString(); + } else { + chargerDockAcOnline = false; + dockBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; + dockBatteryHealth = BatteryManager.BATTERY_HEALTH_UNKNOWN; + dockBatteryPresent = false; + dockBatteryLevel = 0; + dockBatteryVoltage = 0; + dockBatteryTemperature = 0; + dockBatteryTechnology = ""; + } } public void writeToParcel(Parcel p, int flags) { @@ -79,6 +121,18 @@ public class BatteryProperties implements Parcelable { p.writeInt(batteryVoltage); p.writeInt(batteryTemperature); p.writeString(batteryTechnology); + + p.writeInt(dockBatterySupported ? 1 : 0); + if (dockBatterySupported) { + p.writeInt(chargerDockAcOnline ? 1 : 0); + p.writeInt(dockBatteryStatus); + p.writeInt(dockBatteryHealth); + p.writeInt(dockBatteryPresent ? 1 : 0); + p.writeInt(dockBatteryLevel); + p.writeInt(dockBatteryVoltage); + p.writeInt(dockBatteryTemperature); + p.writeString(dockBatteryTechnology); + } } public static final Parcelable.Creator<BatteryProperties> CREATOR diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 2567a41..a800ed6 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -56,7 +56,7 @@ public class Environment { private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage"); private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem"); private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); - private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/vendor/bundled-app"); + private static final File DIR_PREBUNDLED_ROOT = getDirectory(ENV_PREBUNDLED_ROOT, "/bundled-app"); private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled"; diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl index fd01802..43b9650 100644 --- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl +++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl @@ -1,5 +1,6 @@ /* ** Copyright 2013, The Android Open Source Project +** Copyright 2016, The CyanogenMod Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -27,4 +28,5 @@ interface IBatteryPropertiesRegistrar { void registerListener(IBatteryPropertiesListener listener); void unregisterListener(IBatteryPropertiesListener listener); int getProperty(in int id, out BatteryProperty prop); + int getDockProperty(in int id, out BatteryProperty prop); } diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 38037a6..39c12f0 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -117,6 +117,12 @@ public abstract class PowerManagerInternal { public abstract void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis); /** + * Used by the window manager to tell the power manager that the user is no longer actively + * using the device. + */ + public abstract void setUserInactiveOverrideFromWindowManager(); + + /** * Used by device administration to set the maximum screen off timeout. * * This method must only be called by the device administration policy manager. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a738b83..f6642d8 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6438,6 +6438,13 @@ public final class Settings { public static final String AIRPLANE_MODE_TOGGLEABLE_RADIOS = "airplane_mode_toggleable_radios"; /** + * A Long representing a bitmap of profiles that should be disabled when bluetooth starts. + * See {@link android.bluetooth.BluetoothProfile}. + * {@hide} + */ + public static final String BLUETOOTH_DISABLED_PROFILES = "bluetooth_disabled_profiles"; + + /** * The policy for deciding when Wi-Fi should go to sleep (which will in * turn switch to using the mobile data as an Internet connection). * <p> @@ -7693,10 +7700,12 @@ public final class Settings { * The following keys are supported: * * <pre> - * idle_duration (long) + * idle_duration2 (long) * wallclock_threshold (long) * parole_interval (long) * parole_duration (long) + * + * idle_duration (long) // This is deprecated and used to circumvent b/26355386. * </pre> * * <p> @@ -8142,6 +8151,13 @@ public final class Settings { public static final String LTE_SERVICE_FORCED = "lte_service_forced"; /** + * Whether to ignore the representation of outgoing calls set by the network. + * + * @hide + */ + public static final String CONNECTED_LINE_IDENTIFICATION = "connected_line_identification"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -8567,6 +8583,13 @@ public final class Settings { * @hide */ public static final String CONTACT_METADATA_SYNC = "contact_metadata_sync"; + + /** + * Whether to enable cellular on boot. + * The value 1 - enable, 0 - disable + * @hide + */ + public static final String ENABLE_CELLULAR_ON_BOOT = "enable_cellular_on_boot"; } /** diff --git a/core/java/android/provider/ThemesContract.java b/core/java/android/provider/ThemesContract.java deleted file mode 100644 index af7ab26..0000000 --- a/core/java/android/provider/ThemesContract.java +++ /dev/null @@ -1,731 +0,0 @@ -package android.provider; - -import android.net.Uri; - -/** - * @hide - */ -public class ThemesContract { - public static final String AUTHORITY = "com.cyanogenmod.themes"; - public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); - - public static class ThemesColumns { - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "themes"); - - /** - * The unique ID for a row. - * <P>Type: INTEGER (long)</P> - */ - public static final String _ID = "_id"; - - /** - * The user visible title. - * <P>Type: TEXT</P> - */ - public static final String TITLE = "title"; - - /** - * Unique text to identify the apk pkg. ie "com.foo.bar" - * <P>Type: TEXT</P> - */ - public static final String PKG_NAME = "pkg_name"; - - /** - * A 32 bit RRGGBB color representative of the themes color scheme - * <P>Type: INTEGER</P> - */ - public static final String PRIMARY_COLOR = "primary_color"; - - /** - * A 2nd 32 bit RRGGBB color representative of the themes color scheme - * <P>Type: INTEGER</P> - */ - public static final String SECONDARY_COLOR = "secondary_color"; - - /** - * Name of the author of the theme - * <P>Type: TEXT</P> - */ - public static final String AUTHOR = "author"; - - /** - * The time that this row was created on its originating client (msecs - * since the epoch). - * <P>Type: INTEGER</P> - */ - public static final String DATE_CREATED = "created"; - - /** - * URI to an image that shows the homescreen with the theme applied - * since the epoch). - * <P>Type: TEXT</P> - */ - public static final String HOMESCREEN_URI = "homescreen_uri"; - - /** - * URI to an image that shows the lockscreen with theme applied - * <P>Type: TEXT</P> - */ - public static final String LOCKSCREEN_URI = "lockscreen_uri"; - - /** - * URI to an image that shows the style (aka skin) with theme applied - * <P>Type: TEXT</P> - */ - public static final String STYLE_URI = "style_uri"; - - /** - * TODO: Figure structure for actual animation instead of static - * URI to an image of the boot_anim. - * <P>Type: TEXT</P> - */ - public static final String BOOT_ANIM_URI = "bootanim_uri"; - - /** - * URI to an image of the status bar for this theme. - * <P>Type: TEXT</P> - */ - public static final String STATUSBAR_URI = "status_uri"; - - /** - * URI to an image of the fonts in this theme. - * <P>Type: TEXT</P> - */ - public static final String FONT_URI = "font_uri"; - - /** - * URI to an image of the fonts in this theme. - * <P>Type: TEXT</P> - */ - public static final String ICON_URI = "icon_uri"; - - /** - * URI to an image of the fonts in this theme. - * <P>Type: TEXT</P> - */ - public static final String OVERLAYS_URI = "overlays_uri"; - - /** - * 1 if theme modifies the launcher/homescreen else 0 - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_LAUNCHER = "mods_homescreen"; - - /** - * 1 if theme modifies the lockscreen else 0 - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_LOCKSCREEN = "mods_lockscreen"; - - /** - * 1 if theme modifies icons else 0 - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_ICONS = "mods_icons"; - - /** - * 1 if theme modifies fonts - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_FONTS = "mods_fonts"; - - /** - * 1 if theme modifies boot animation - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_BOOT_ANIM = "mods_bootanim"; - - /** - * 1 if theme modifies notifications - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_NOTIFICATIONS = "mods_notifications"; - - /** - * 1 if theme modifies alarm sounds - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_ALARMS = "mods_alarms"; - - /** - * 1 if theme modifies ringtones - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_RINGTONES = "mods_ringtones"; - - /** - * 1 if theme has overlays - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_OVERLAYS = "mods_overlays"; - - /** - * 1 if theme has an overlay for SystemUI/StatusBar - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_STATUS_BAR = "mods_status_bar"; - - /** - * 1 if theme has an overlay for SystemUI/NavBar - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_NAVIGATION_BAR = "mods_navigation_bar"; - - /** - * 1 if theme has a live lock screen - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String MODIFIES_LIVE_LOCK_SCREEN = "mods_live_lock_screen"; - - /** - * URI to the theme's wallpaper. We should support multiple wallpaper - * but for now we will just have 1. - * <P>Type: TEXT</P> - */ - public static final String WALLPAPER_URI = "wallpaper_uri"; - - /** - * 1 if this row should actually be presented as a theme to the user. - * For example if a "theme" only modifies one component (ex icons) then - * we do not present it to the user under the themes table. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String PRESENT_AS_THEME = "present_as_theme"; - - /** - * 1 if this theme is a legacy theme. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String IS_LEGACY_THEME = "is_legacy_theme"; - - /** - * 1 if this theme is the system default theme. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String IS_DEFAULT_THEME = "is_default_theme"; - - /** - * 1 if this theme is a legacy iconpack. A legacy icon pack is an APK that was written - * for Trebuchet or a 3rd party launcher. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String IS_LEGACY_ICONPACK = "is_legacy_iconpack"; - - /** - * install/update time in millisecs. When the row is inserted this column - * is populated by the PackageInfo. It is used for syncing to PM - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String LAST_UPDATE_TIME = "updateTime"; - - /** - * install time in millisecs. When the row is inserted this column - * is populated by the PackageInfo. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String INSTALL_TIME = "install_time"; - - /** - * The target API this theme supports - * is populated by the PackageInfo. - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String TARGET_API = "target_api"; - - /** - * The install state of the theme. - * Can be one of the following: - * {@link InstallState#UNKNOWN} - * {@link InstallState#INSTALLING} - * {@link InstallState#UPDATING} - * {@link InstallState#INSTALLED} - * <P>Type: INTEGER</P> - * <P>Default: 0</P> - */ - public static final String INSTALL_STATE = "install_state"; - - public static class InstallState { - public static final int UNKNOWN = 0; - public static final int INSTALLING = 1; - public static final int UPDATING = 2; - public static final int INSTALLED = 3; - } - } - - /** - * Key-value table which assigns a component (ex wallpaper) to a theme's package - */ - public static class MixnMatchColumns { - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "mixnmatch"); - - /** - * The unique key for a row. See the KEY_* constants - * for valid examples - * <P>Type: TEXT</P> - */ - public static final String COL_KEY = "key"; - - /** - * The package name that corresponds to a given component. - * <P>Type: String</P> - */ - public static final String COL_VALUE = "value"; - - /** - * The package name that corresponds to where this component was applied from previously - * <P>Type: String</P> - */ - public static final String COL_PREV_VALUE = "previous_value"; - - /** - * Time when this entry was last updated - * <P>Type: INTEGER</P> - */ - public static final String COL_UPDATE_TIME = "update_time"; - - /* - * The unique ID for the component within a theme. - * Always 0 unless multiples of a component exist. - * <P>Type: INTEGER (long)</P> - */ - public static final String COL_COMPONENT_ID = "component_id"; - - /** - * Valid keys - */ - public static final String KEY_HOMESCREEN = "mixnmatch_homescreen"; - public static final String KEY_LOCKSCREEN = "mixnmatch_lockscreen"; - public static final String KEY_ICONS = "mixnmatch_icons"; - public static final String KEY_STATUS_BAR = "mixnmatch_status_bar"; - public static final String KEY_BOOT_ANIM = "mixnmatch_boot_anim"; - public static final String KEY_FONT = "mixnmatch_font"; - public static final String KEY_ALARM = "mixnmatch_alarm"; - public static final String KEY_NOTIFICATIONS = "mixnmatch_notifications"; - public static final String KEY_RINGTONE = "mixnmatch_ringtone"; - public static final String KEY_OVERLAYS = "mixnmatch_overlays"; - public static final String KEY_NAVIGATION_BAR = "mixnmatch_navigation_bar"; - public static final String KEY_LIVE_LOCK_SCREEN = "mixnmatch_live_lock_screen"; - - public static final String[] ROWS = { KEY_HOMESCREEN, - KEY_LOCKSCREEN, - KEY_ICONS, - KEY_STATUS_BAR, - KEY_BOOT_ANIM, - KEY_FONT, - KEY_NOTIFICATIONS, - KEY_RINGTONE, - KEY_ALARM, - KEY_OVERLAYS, - KEY_NAVIGATION_BAR, - KEY_LIVE_LOCK_SCREEN - }; - - /** - * For a given key value in the MixNMatch table, return the column - * associated with it in the Themes Table. This is useful for URI based - * elements like wallpaper where the caller wishes to determine the - * wallpaper URI. - */ - public static String componentToImageColName(String component) { - if (component.equals(MixnMatchColumns.KEY_HOMESCREEN)) { - return ThemesColumns.HOMESCREEN_URI; - } else if (component.equals(MixnMatchColumns.KEY_LOCKSCREEN)) { - return ThemesColumns.LOCKSCREEN_URI; - } else if (component.equals(MixnMatchColumns.KEY_BOOT_ANIM)) { - return ThemesColumns.BOOT_ANIM_URI; - } else if (component.equals(MixnMatchColumns.KEY_FONT)) { - return ThemesColumns.FONT_URI; - } else if (component.equals(MixnMatchColumns.KEY_ICONS)) { - return ThemesColumns.ICON_URI; - } else if (component.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - return ThemesColumns.STATUSBAR_URI; - } else if (component.equals(MixnMatchColumns.KEY_NOTIFICATIONS)) { - throw new IllegalArgumentException("Notifications mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_RINGTONE)) { - throw new IllegalArgumentException("Ringtone mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_OVERLAYS)) { - return ThemesColumns.OVERLAYS_URI; - } else if (component.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - throw new IllegalArgumentException( - "Status bar mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_NAVIGATION_BAR)) { - throw new IllegalArgumentException( - "Navigation bar mixnmatch component does not have a related column"); - } else if (component.equals(MixnMatchColumns.KEY_LIVE_LOCK_SCREEN)) { - throw new IllegalArgumentException( - "Live lock screen mixnmatch component does not have a related column"); - } - return null; - } - - /** - * A component in the themes table (IE "mods_wallpaper") has an - * equivalent key in mixnmatch table - */ - public static String componentToMixNMatchKey(String component) { - if (component.equals(ThemesColumns.MODIFIES_LAUNCHER)) { - return MixnMatchColumns.KEY_HOMESCREEN; - } else if (component.equals(ThemesColumns.MODIFIES_ICONS)) { - return MixnMatchColumns.KEY_ICONS; - } else if (component.equals(ThemesColumns.MODIFIES_LOCKSCREEN)) { - return MixnMatchColumns.KEY_LOCKSCREEN; - } else if (component.equals(ThemesColumns.MODIFIES_FONTS)) { - return MixnMatchColumns.KEY_FONT; - } else if (component.equals(ThemesColumns.MODIFIES_BOOT_ANIM)) { - return MixnMatchColumns.KEY_BOOT_ANIM; - } else if (component.equals(ThemesColumns.MODIFIES_ALARMS)) { - return MixnMatchColumns.KEY_ALARM; - } else if (component.equals(ThemesColumns.MODIFIES_NOTIFICATIONS)) { - return MixnMatchColumns.KEY_NOTIFICATIONS; - } else if (component.equals(ThemesColumns.MODIFIES_RINGTONES)) { - return MixnMatchColumns.KEY_RINGTONE; - } else if (component.equals(ThemesColumns.MODIFIES_OVERLAYS)) { - return MixnMatchColumns.KEY_OVERLAYS; - } else if (component.equals(ThemesColumns.MODIFIES_STATUS_BAR)) { - return MixnMatchColumns.KEY_STATUS_BAR; - } else if (component.equals(ThemesColumns.MODIFIES_NAVIGATION_BAR)) { - return MixnMatchColumns.KEY_NAVIGATION_BAR; - } else if (component.equals(ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN)) { - return MixnMatchColumns.KEY_LIVE_LOCK_SCREEN; - } - return null; - } - - /** - * A mixnmatch key in has an - * equivalent value in the themes table - */ - public static String mixNMatchKeyToComponent(String mixnmatchKey) { - if (mixnmatchKey.equals(MixnMatchColumns.KEY_HOMESCREEN)) { - return ThemesColumns.MODIFIES_LAUNCHER; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_ICONS)) { - return ThemesColumns.MODIFIES_ICONS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_LOCKSCREEN)) { - return ThemesColumns.MODIFIES_LOCKSCREEN; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_FONT)) { - return ThemesColumns.MODIFIES_FONTS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_BOOT_ANIM)) { - return ThemesColumns.MODIFIES_BOOT_ANIM; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_ALARM)) { - return ThemesColumns.MODIFIES_ALARMS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_NOTIFICATIONS)) { - return ThemesColumns.MODIFIES_NOTIFICATIONS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_RINGTONE)) { - return ThemesColumns.MODIFIES_RINGTONES; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_OVERLAYS)) { - return ThemesColumns.MODIFIES_OVERLAYS; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_STATUS_BAR)) { - return ThemesColumns.MODIFIES_STATUS_BAR; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_NAVIGATION_BAR)) { - return ThemesColumns.MODIFIES_NAVIGATION_BAR; - } else if (mixnmatchKey.equals(MixnMatchColumns.KEY_LIVE_LOCK_SCREEN)) { - return ThemesColumns.MODIFIES_LIVE_LOCK_SCREEN; - } - return null; - } - } - - /** - * Table containing cached preview files for a given theme - */ - public static class PreviewColumns { - /** - * Uri for retrieving the previews table. - * Querying the themes provider using this URI will return a cursor with a key and value - * columns, and a row for each component. - */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "previews"); - - /** - * Uri for retrieving the previews for the currently applied components. - * Querying the themes provider using this URI will return a cursor with a single row - * containing all the previews for the components that are currently applied. - */ - public static final Uri APPLIED_URI = Uri.withAppendedPath(AUTHORITY_URI, - "applied_previews"); - - /** - * Uri for retrieving the default previews for the theme. - * Querying the themes provider using this URI will return a cursor with a single row - * containing all the previews for the default components of the current theme. - */ - public static final Uri COMPONENTS_URI = Uri.withAppendedPath(AUTHORITY_URI, - "components_previews"); - - /** - * The unique ID for a row. - * <P>Type: INTEGER (long)</P> - */ - public static final String _ID = "_id"; - - /** - * The unique ID for the theme these previews belong to. - * <P>Type: INTEGER (long)</P> - */ - public static final String THEME_ID = "theme_id"; - - /** - * The unique ID for the component within a theme. - * <P>Type: INTEGER (long)</P> - */ - public static final String COMPONENT_ID = "component_id"; - - /** - * The unique key for a row. See the Valid key constants section below - * for valid examples - * <P>Type: TEXT</P> - */ - public static final String COL_KEY = "key"; - - /** - * The package name that corresponds to a given component. - * <P>Type: String</P> - */ - public static final String COL_VALUE = "value"; - - /** - * Valid keys - */ - - /** - * Cached image of the themed status bar background. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_BACKGROUND = "statusbar_background"; - - /** - * Cached image of the themed bluetooth status icon. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_BLUETOOTH_ICON = "statusbar_bluetooth_icon"; - - /** - * Cached image of the themed wifi status icon. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_WIFI_ICON = "statusbar_wifi_icon"; - - /** - * Cached image of the themed cellular signal status icon. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_SIGNAL_ICON = "statusbar_signal_icon"; - - /** - * Cached image of the themed battery using portrait style. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_BATTERY_PORTRAIT = "statusbar_battery_portrait"; - - /** - * Cached image of the themed battery using landscape style. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_BATTERY_LANDSCAPE = "statusbar_battery_landscape"; - - /** - * Cached image of the themed battery using circle style. - * <P>Type: String (file path)</P> - */ - public static final String STATUSBAR_BATTERY_CIRCLE = "statusbar_battery_circle"; - - /** - * The themed color used for clock text in the status bar. - * <P>Type: INTEGER (int)</P> - */ - public static final String STATUSBAR_CLOCK_TEXT_COLOR = "statusbar_clock_text_color"; - - /** - * The themed margin value between the wifi and rssi signal icons. - * <P>Type: INTEGER (int)</P> - */ - public static final String STATUSBAR_WIFI_COMBO_MARGIN_END = "wifi_combo_margin_end"; - - /** - * Cached image of the themed navigation bar background. - * <P>Type: String (file path)</P> - */ - public static final String NAVBAR_BACKGROUND = "navbar_background"; - - /** - * Cached image of the themed back button. - * <P>Type: String (file path)</P> - */ - public static final String NAVBAR_BACK_BUTTON = "navbar_back_button"; - - /** - * Cached image of the themed home button. - * <P>Type: String (file path)</P> - */ - public static final String NAVBAR_HOME_BUTTON = "navbar_home_button"; - - /** - * Cached image of the themed recents button. - * <P>Type: String (file path)</P> - */ - public static final String NAVBAR_RECENT_BUTTON = "navbar_recent_button"; - - /** - * Cached image of the 1/3 icons - * <P>Type: String (file path)</P> - */ - public static final String ICON_PREVIEW_1 = "icon_preview_1"; - - /** - * Cached image of the 2/3 icons - * <P>Type: String (file path)</P> - */ - public static final String ICON_PREVIEW_2 = "icon_preview_2"; - - /** - * Cached image of the 3/3 icons - * <P>Type: String (file path)</P> - */ - public static final String ICON_PREVIEW_3 = "icon_preview_3"; - - /** - * Full path to the theme's wallpaper asset. - * <P>Type: String (file path)</P> - */ - public static final String WALLPAPER_FULL = "wallpaper_full"; - - /** - * Cached preview of the theme's wallpaper which is larger than the thumbnail - * but smaller than the full sized wallpaper. - * <P>Type: String (file path)</P> - */ - public static final String WALLPAPER_PREVIEW = "wallpaper_preview"; - - /** - * Cached thumbnail of the theme's wallpaper - * <P>Type: String (file path)</P> - */ - public static final String WALLPAPER_THUMBNAIL = "wallpaper_thumbnail"; - - /** - * Cached preview of the theme's lockscreen wallpaper which is larger than the thumbnail - * but smaller than the full sized lockscreen wallpaper. - * <P>Type: String (file path)</P> - */ - public static final String LOCK_WALLPAPER_PREVIEW = "lock_wallpaper_preview"; - - /** - * Cached thumbnail of the theme's lockscreen wallpaper - * <P>Type: String (file path)</P> - */ - public static final String LOCK_WALLPAPER_THUMBNAIL = "lock_wallpaper_thumbnail"; - - /** - * Cached preview of UI controls representing the theme's style - * <P>Type: String (file path)</P> - */ - public static final String STYLE_PREVIEW = "style_preview"; - - /** - * Cached thumbnail preview of UI controls representing the theme's style - * <P>Type: String (file path)</P> - */ - public static final String STYLE_THUMBNAIL = "style_thumbnail"; - - /** - * Cached thumbnail of the theme's boot animation - * <P>Type: String (file path)</P> - */ - public static final String BOOTANIMATION_THUMBNAIL = "bootanimation_thumbnail"; - - /** - * Cached preview of live lock screen - * <P>Type: String (file path)</P> - */ - public static final String LIVE_LOCK_SCREEN_PREVIEW = "live_lock_screen_preview"; - - /** - * Cached thumbnail preview of live lock screen - * <P>Type: String (file path)</P> - */ - public static final String LIVE_LOCK_SCREEN_THUMBNAIL = "live_lock_screen_thumbnail"; - - public static final String[] VALID_KEYS = { - STATUSBAR_BACKGROUND, - STATUSBAR_BLUETOOTH_ICON, - STATUSBAR_WIFI_ICON, - STATUSBAR_SIGNAL_ICON, - STATUSBAR_BATTERY_PORTRAIT, - STATUSBAR_BATTERY_LANDSCAPE, - STATUSBAR_BATTERY_CIRCLE, - STATUSBAR_CLOCK_TEXT_COLOR, - STATUSBAR_WIFI_COMBO_MARGIN_END, - NAVBAR_BACKGROUND, - NAVBAR_BACK_BUTTON, - NAVBAR_HOME_BUTTON, - NAVBAR_RECENT_BUTTON, - ICON_PREVIEW_1, - ICON_PREVIEW_2, - ICON_PREVIEW_3, - WALLPAPER_FULL, - WALLPAPER_PREVIEW, - WALLPAPER_THUMBNAIL, - LOCK_WALLPAPER_PREVIEW, - LOCK_WALLPAPER_THUMBNAIL, - STYLE_PREVIEW, - STYLE_THUMBNAIL, - BOOTANIMATION_THUMBNAIL, - LIVE_LOCK_SCREEN_PREVIEW, - LIVE_LOCK_SCREEN_THUMBNAIL, - }; - } - - public static class Intent { - /** - * Action sent from the provider when a theme has been fully installed. Fully installed - * means that the apk was installed by PackageManager and the theme resources were - * processed and cached by {@link com.android.server.ThemeService} - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_INSTALLED = - "themescontract.intent.action.THEME_INSTALLED"; - - /** - * Action sent from the provider when a theme has been updated. - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_UPDATED = - "themescontract.intent.action.THEME_UPDATED"; - - /** - * Action sent from the provider when a theme has been removed. - * Requires the {@link android.Manifest.permission#READ_THEMES} permission to receive - * this broadcast. - */ - public static final String ACTION_THEME_REMOVED = - "themescontract.intent.action.THEME_REMOVED"; - - /** - * Uri scheme used to broadcast the theme's package name when broadcasting - * {@link android.provider.ThemesContract.Intent#ACTION_THEME_INSTALLED} or - * {@link android.provider.ThemesContract.Intent#ACTION_THEME_REMOVED} - */ - public static final String URI_SCHEME_PACKAGE = "package"; - } -} diff --git a/core/java/android/service/gesture/EdgeGestureManager.java b/core/java/android/service/gesture/EdgeGestureManager.java deleted file mode 100644 index 7c0ab2e..0000000 --- a/core/java/android/service/gesture/EdgeGestureManager.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package android.service.gesture; - -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.service.gesture.IEdgeGestureActivationListener; -import android.service.gesture.IEdgeGestureHostCallback; -import android.service.gesture.IEdgeGestureService; -import android.util.Slog; - -import com.android.internal.util.gesture.EdgeGesturePosition; - -/** - * This is a simple Manager class for edge gesture service on the application side. The application need - * {@code INJECT_EVENTS} permission to register {@code EdgeGestureActivationListener}s.<br> - * See {@link android.service.gesture.IEdgeGestureService} for more information. - * - * @see android.service.gesture.IEdgeGestureService - * @hide - */ -public class EdgeGestureManager { - public static final String TAG = "EdgeGestureManager"; - public static final boolean DEBUG = false; - - private static EdgeGestureManager sInstance; - - private final IEdgeGestureService mPs; - - public static abstract class EdgeGestureActivationListener { - private Handler mHandler; - private IEdgeGestureHostCallback mCallback; - - private class Delegator extends IEdgeGestureActivationListener.Stub { - public void onEdgeGestureActivation(final int touchX, final int touchY, final int positionIndex, final int flags) - throws RemoteException { - mHandler.post(new Runnable() { - public void run() { - EdgeGestureActivationListener.this.onEdgeGestureActivation(touchX, touchY, EdgeGesturePosition.values()[positionIndex], flags); - } - }); - } - } - private Delegator mDelegator; - - public EdgeGestureActivationListener() { - this(Looper.getMainLooper()); - } - - public EdgeGestureActivationListener(Looper looper) { - mHandler = new Handler(looper); - mDelegator = new Delegator(); - } - - /* package */ void setHostCallback(IEdgeGestureHostCallback hostCallback) { - mCallback = hostCallback; - } - - /** - * Override this to receive activations from the edge gesture service. - * - * @param touchX the last X position a touch event was registered. - * @param touchY the last Y position a touch event was registered. - * @param position the position of the activation. - * @param flags currently 0. - * @see IEdgeGestureActivationListener#onEdgeGestureActivation(int, int, int, int) - */ - public abstract void onEdgeGestureActivation(int touchX, int touchY, EdgeGesturePosition position, int flags); - - /** - * After being activated, this allows the edge gesture control to steal focus from the current - * window. - * - * @see IEdgeGestureHostCallback#gainTouchFocus(IBinder) - */ - public boolean gainTouchFocus(IBinder applicationWindowToken) { - try { - return mCallback.gainTouchFocus(applicationWindowToken); - } catch (RemoteException e) { - Slog.w(TAG, "gainTouchFocus failed: " + e.getMessage()); - /* fall through */ - } - return false; - } - - public boolean dropEventsUntilLift() { - try { - return mCallback.dropEventsUntilLift(); - } catch (RemoteException e) { - Slog.w(TAG, "dropNextEvents failed: " + e.getMessage()); - /* fall through */ - } - return false; - } - - /** - * Turns listening for edge gesture activation gestures on again, after it was disabled during - * the call to the listener. - * - * @see IEdgeGestureHostCallback#restoreListenerState() - */ - public void restoreListenerState() { - if (DEBUG) { - Slog.d(TAG, "restore listener state: " + Thread.currentThread().getName()); - } - try { - mCallback.restoreListenerState(); - } catch (RemoteException e) { - Slog.w(TAG, "restoreListenerState failed: " + e.getMessage()); - /* fall through */ - } - } - } - - private EdgeGestureManager(IEdgeGestureService ps) { - mPs = ps; - } - - /** - * Gets an instance of the edge gesture manager. - * - * @return The edge gesture manager instance. - * @hide - */ - public static EdgeGestureManager getInstance() { - synchronized (EdgeGestureManager.class) { - if (sInstance == null) { - IBinder b = ServiceManager.getService("edgegestureservice"); - sInstance = new EdgeGestureManager(IEdgeGestureService.Stub.asInterface(b)); - } - return sInstance; - } - } - - /** - * Checks if the edge gesture service is present. - * <p> - * Since the service is only started at boot time and is bound to the system server, this - * is constant for the devices up time. - * - * @return {@code true} when the edge gesture service is running on this device. - * @hide - */ - public boolean isPresent() { - return mPs != null; - } - - /** - * Register a listener for edge gesture activation gestures. Initially the listener - * is set to listen for no position. Use updateedge gestureActivationListener() to - * bind the listener to positions. - * - * @param listener is the activation listener. - * @return {@code true} if the registration was successful. - * @hide - */ - public boolean setEdgeGestureActivationListener(EdgeGestureActivationListener listener) { - if (DEBUG) { - Slog.d(TAG, "Set edge gesture activation listener"); - } - try { - IEdgeGestureHostCallback callback = mPs.registerEdgeGestureActivationListener(listener.mDelegator); - listener.setHostCallback(callback); - return true; - } catch (RemoteException e) { - Slog.e(TAG, "Failed to set edge gesture activation listener: " + e.getMessage()); - return false; - } - } - - /** - * Update the listener to react on gestures in the given positions. - * - * @param listener is a already registered listener. - * @param positions is a bit mask describing the positions to listen to. - * @hide - */ - public void updateEdgeGestureActivationListener(EdgeGestureActivationListener listener, int positions) { - if (DEBUG) { - Slog.d(TAG, "Update edge gesture activation listener: 0x" + Integer.toHexString(positions)); - } - try { - mPs.updateEdgeGestureActivationListener(listener.mDelegator.asBinder(), positions); - } catch (RemoteException e) { - Slog.e(TAG, "Failed to update edge gesture activation listener: " + e.getMessage()); - } - } - -} diff --git a/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl b/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl deleted file mode 100644 index 0c9b24a..0000000 --- a/core/java/android/service/gesture/IEdgeGestureActivationListener.aidl +++ /dev/null @@ -1,14 +0,0 @@ - -package android.service.gesture; - -import android.view.InputEvent; - -/** @hide */ -interface IEdgeGestureActivationListener { - - /** Called when a gesture is detected that fits to the activation gesture. At this point in - * time gesture detection is disabled. Call IEdgeGestureHostCallback.restoreState() to - * recover from this. - */ - oneway void onEdgeGestureActivation(int touchX, int touchY, int positionIndex, int flags); -}
\ No newline at end of file diff --git a/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl b/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl deleted file mode 100644 index c261550..0000000 --- a/core/java/android/service/gesture/IEdgeGestureHostCallback.aidl +++ /dev/null @@ -1,20 +0,0 @@ -package android.service.gesture; - -/** @hide */ -interface IEdgeGestureHostCallback { - - /** After being activated, this allows to steal focus from the current - * window - */ - boolean gainTouchFocus(IBinder windowToken); - - /** Turns listening for activation gestures on again, after it was disabled during - * the call to the listener. - */ - oneway void restoreListenerState(); - - /* - * Tells filter to drop all events till touch up - */ - boolean dropEventsUntilLift(); -}
\ No newline at end of file diff --git a/core/java/android/service/gesture/IEdgeGestureService.aidl b/core/java/android/service/gesture/IEdgeGestureService.aidl deleted file mode 100644 index 342cf71..0000000 --- a/core/java/android/service/gesture/IEdgeGestureService.aidl +++ /dev/null @@ -1,20 +0,0 @@ -package android.service.gesture; - -import android.service.gesture.IEdgeGestureActivationListener; -import android.service.gesture.IEdgeGestureHostCallback; - -/** @hide */ -interface IEdgeGestureService { - - /** Register a listener for activation gestures. Initially the listener - * is set to listen for no position. Use updateEdgeGestureActivationListener() to - * bind the listener to positions. - * Use the returned IEdgeGestureHostCallback to manipulate the state after activation. - */ - IEdgeGestureHostCallback registerEdgeGestureActivationListener(in IEdgeGestureActivationListener listener); - - /** Update the listener to react on gestures in the given positions. - */ - void updateEdgeGestureActivationListener(in IBinder listener, int positionFlags); - -}
\ No newline at end of file diff --git a/core/java/android/service/gesture/package.html b/core/java/android/service/gesture/package.html deleted file mode 100644 index c9f96a6..0000000 --- a/core/java/android/service/gesture/package.html +++ /dev/null @@ -1,5 +0,0 @@ -<body> - -{@hide} - -</body> diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index fa347b9..22ad634 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1130,20 +1130,31 @@ public abstract class Layout { */ public int getOffsetForHorizontal(int line, float horiz) { // TODO: use Paint.getOffsetForAdvance to avoid binary search - int max = getLineEnd(line) - 1; - int min = getLineStart(line); + final int lineEndOffset = getLineEnd(line); + final int lineStartOffset = getLineStart(line); + Directions dirs = getLineDirections(line); - if (line == getLineCount() - 1) - max++; + TextLine tl = TextLine.obtain(); + // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here. + tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs, + false, null); - int best = min; + final int max; + if (line == getLineCount() - 1) { + max = lineEndOffset; + } else { + max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset, + !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset; + } + int best = lineStartOffset; float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz); for (int i = 0; i < dirs.mDirections.length; i += 2) { - int here = min + dirs.mDirections[i]; + int here = lineStartOffset + dirs.mDirections[i]; int there = here + (dirs.mDirections[i+1] & RUN_LENGTH_MASK); - int swap = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0 ? -1 : 1; + boolean isRtl = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0; + int swap = isRtl ? -1 : 1; if (there > max) there = max; @@ -1163,23 +1174,23 @@ public abstract class Layout { low = here + 1; if (low < there) { - low = getOffsetAtStartOf(low); - - float dist = Math.abs(getPrimaryHorizontal(low) - horiz); - - int aft = TextUtils.getOffsetAfter(mText, low); - if (aft < there) { - float other = Math.abs(getPrimaryHorizontal(aft) - horiz); - - if (other < dist) { - dist = other; - low = aft; + int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset; + low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset; + if (low >= here && low < there) { + float dist = Math.abs(getPrimaryHorizontal(low) - horiz); + if (aft < there) { + float other = Math.abs(getPrimaryHorizontal(aft) - horiz); + + if (other < dist) { + dist = other; + low = aft; + } } - } - if (dist < bestdist) { - bestdist = dist; - best = low; + if (dist < bestdist) { + bestdist = dist; + best = low; + } } } @@ -1198,6 +1209,7 @@ public abstract class Layout { best = max; } + TextLine.recycle(tl); return best; } diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 39e8694..3592187 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -718,13 +718,14 @@ class TextLine { * @param bottom the bottom of the line * @param fmi receives metrics information, can be null * @param needWidth true if the width of the run is needed + * @param offset the offset for the purpose of measuring * @return the signed width of the run based on the run direction; only * valid if needWidth is true */ private float handleText(TextPaint wp, int start, int end, int contextStart, int contextEnd, boolean runIsRtl, Canvas c, float x, int top, int y, int bottom, - FontMetricsInt fmi, boolean needWidth) { + FontMetricsInt fmi, boolean needWidth, int offset) { // Get metrics first (even for empty strings or "0" width runs) if (fmi != null) { @@ -742,11 +743,11 @@ class TextLine { if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) { if (mCharsValid) { ret = wp.getRunAdvance(mChars, start, end, contextStart, contextEnd, - runIsRtl, end); + runIsRtl, offset); } else { int delta = mStart; ret = wp.getRunAdvance(mText, delta + start, delta + end, - delta + contextStart, delta + contextEnd, runIsRtl, delta + end); + delta + contextStart, delta + contextEnd, runIsRtl, delta + offset); } } @@ -895,8 +896,8 @@ class TextLine { TextPaint wp = mWorkPaint; wp.set(mPaint); final int mlimit = measureLimit; - return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top, - y, bottom, fmi, needWidth || mlimit < measureLimit); + return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top, + y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit); } mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit); @@ -940,13 +941,14 @@ class TextLine { } for (int j = i, jnext; j < mlimit; j = jnext) { - jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) - + jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) - mStart; + int offset = Math.min(jnext, mlimit); wp.set(mPaint); for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) { // Intentionally using >= and <= as explained above - if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) || + if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) || (mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue; CharacterStyle span = mCharacterStyleSpanSet.spans[k]; @@ -958,7 +960,7 @@ class TextLine { wp.setHyphenEdit(0); } x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x, - top, y, bottom, fmi, needWidth || jnext < measureLimit); + top, y, bottom, fmi, needWidth || jnext < measureLimit, offset); } } diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index 2cc91b9..6fc8ae5 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -125,15 +125,35 @@ public class Patterns { + "|[1-9][0-9]|[0-9]))"); /** + * Match the characters without containing chinese characters + * @hide + */ + private static final String GOOD_IRI_HOST_CHAR = + "a-zA-Z0-9\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF" + + "\uF900-\uFDCF\uFDF0-\uFEFF"; + + /** * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets. */ - private static final String IRI - = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}"; + private static final String IRI = + "[" + GOOD_IRI_HOST_CHAR + "]([" + GOOD_IRI_HOST_CHAR + "\\-]{0,61}[" + + GOOD_IRI_HOST_CHAR + "]){0,1}"; private static final String GOOD_GTLD_CHAR = - "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF"; + "a-zA-Z\u00A0-\u2FFF\u3040-\u4DFF\u9FA6-\uD7FF" + + "\uF900-\uFDCF\uFDF0-\uFEFF"; private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}"; private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD; + // Halfwidth and fullwidth forms + private static final String HALF_FULL_WIDTH_CHAR = "\uFF00-\uFFEF"; + // Symbols and punctuation + private static final String SYMBOLS_PUNCTUATION_CHAR = "\u3000-\u303F"; + // Chinese characters + private static final String CHINESE_CHAR = "\u4E00-\u9FA5"; + // Forbidden characters, should remove from URL, + private static final String FORBIDDEN_CHAR = + "[" + SYMBOLS_PUNCTUATION_CHAR + CHINESE_CHAR + + HALF_FULL_WIDTH_CHAR + "]"; public static final Pattern DOMAIN_NAME = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")"); @@ -149,11 +169,15 @@ public class Patterns { + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?" + "(?:" + DOMAIN_NAME + ")" + "(?:\\:\\d{1,5})?)" // plus option port number - + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params - + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?" - + "(?:\\b|$)"); // and finally, a word boundary or end of - // input. This is to stop foo.sure from - // matching as foo.su + + "(\\/(?:(?:[" + GOOD_IRI_HOST_CHAR + + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params + + "\\-\\.\\+\\!\\*\\'\\(\\)\\_])|(?:\\,[" + GOOD_IRI_HOST_CHAR + + "])|(?:\\%[a-fA-F0-9]{2}))*)?" + + "(?:(?=" + FORBIDDEN_CHAR + + ")|\\b|$)"); + // and finally, a word boundary or end of input. This is to stop + // foo.sure from matching as foo.su + // also should remove forbidden characters from end of URL. public static final Pattern EMAIL_ADDRESS = Pattern.compile( diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index d43b962..85321f9 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -567,6 +567,8 @@ public final class DisplayInfo implements Parcelable { } else if (type == Display.TYPE_BUILT_IN && (flags & Display.FLAG_PRESENTATION) == 0) { outMetrics.setDensity(DisplayMetrics.DENSITY_PREFERRED); + } else { + outMetrics.setDensity(logicalDensityDpi); } } diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 7642ed9..5f88c11 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -256,16 +256,13 @@ public final class InputDevice implements Parcelable { public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE; /** - * The input source is a touch device whose motions should be interpreted as gestures. - * - * For example, an upward swipe should be treated the same as a swipe of the touchscreen. - * The same should apply for left, right, down swipes. Complex gestures may also be input. + * The input source is a rotating encoder device whose motions should be interpreted as akin to + * those of a scroll wheel. * * @see #SOURCE_CLASS_NONE - * - * @hide + * {@hide} */ - public static final int SOURCE_GESTURE_SENSOR = 0x00400000 | SOURCE_CLASS_NONE; + public static final int SOURCE_ROTARY_ENCODER = 0x00400000 | SOURCE_CLASS_NONE; /** * The input source is a joystick. @@ -284,6 +281,18 @@ public final class InputDevice implements Parcelable { public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON; /** + * The input source is a touch device whose motions should be interpreted as gestures. + * + * For example, an upward swipe should be treated the same as a swipe of the touchscreen. + * The same should apply for left, right, down swipes. Complex gestures may also be input. + * + * @see #SOURCE_CLASS_NONE + * + * @hide + */ + public static final int SOURCE_GESTURE_SENSOR = 0x10000000 | SOURCE_CLASS_NONE; + + /** * A special input source constant that is used when filtering input devices * to match devices that provide any type of input source. */ diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index d5847be..d128288 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -761,6 +761,19 @@ public class KeyEvent extends InputEvent implements Parcelable { * Backs out one level of a navigation hierarchy or collapses the item that currently has * focus. */ public static final int KEYCODE_NAVIGATE_OUT = 263; + /** Key code constant: Primary stem key for Wear + * Main power/reset button on watch. + * @hide */ + public static final int KEYCODE_STEM_PRIMARY = 264; + /** Key code constant: Generic stem key 1 for Wear + * @hide */ + public static final int KEYCODE_STEM_1 = 265; + /** Key code constant: Generic stem key 2 for Wear + * @hide */ + public static final int KEYCODE_STEM_2 = 266; + /** Key code constant: Generic stem key 3 for Wear + * @hide */ + public static final int KEYCODE_STEM_3 = 267; /** Key code constant: Skip forward media key. */ public static final int KEYCODE_MEDIA_SKIP_FORWARD = 272; /** Key code constant: Skip backward media key. */ @@ -771,8 +784,11 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: Step backward media key. * Steps media backward, one frame at a time. */ public static final int KEYCODE_MEDIA_STEP_BACKWARD = 275; + /** Key code constant: put device to sleep unless a wakelock is held. + * @hide */ + public static final int KEYCODE_SOFT_SLEEP = 276; - private static final int LAST_KEYCODE = KEYCODE_MEDIA_STEP_BACKWARD; + private static final int LAST_KEYCODE = KEYCODE_SOFT_SLEEP; // NOTE: If you add a new keycode here you must also add it to: // isSystem() @@ -1836,6 +1852,9 @@ public class KeyEvent extends InputEvent implements Parcelable { case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_CAMERA: case KeyEvent.KEYCODE_FOCUS: + case KeyEvent.KEYCODE_STEM_1: + case KeyEvent.KEYCODE_STEM_2: + case KeyEvent.KEYCODE_STEM_3: return true; } return false; diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 6026d04..527d7e5 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -962,6 +962,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_TILT = 25; /** + * Axis constant: Generic scroll axis of a motion event. + * <p> + * <ul> + * <li>Reports the relative movement of the generic scrolling device. + * </ul> + * </p><p> + * This axis should be used for scroll events that are neither strictly vertical nor horizontal. + * A good example would be the rotation of a rotary encoder input device. + * </p> + * + * @see #getAxisValue(int, int) + * {@hide} + */ + public static final int AXIS_SCROLL = 26; + + /** * Axis constant: Generic 1 axis of a motion event. * The interpretation of a generic axis is device-specific. * @@ -1171,6 +1187,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { names.append(AXIS_BRAKE, "AXIS_BRAKE"); names.append(AXIS_DISTANCE, "AXIS_DISTANCE"); names.append(AXIS_TILT, "AXIS_TILT"); + names.append(AXIS_SCROLL, "AXIS_SCROLL"); names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1"); names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2"); names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3"); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 93345c2..4b56352 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16940,8 +16940,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ @CallSuper protected boolean verifyDrawable(Drawable who) { - return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who) - || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); + // Avoid verifying the scroll bar drawable so that we don't end up in + // an invalidation loop. This effectively prevents the scroll bar + // drawable from triggering invalidations and scheduling runnables. + return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 42402eb..9569422 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -174,6 +174,10 @@ public final class ViewRootImpl implements ViewParent, // so the window should no longer be active. boolean mStopped = false; + // Set to true if the owner of this window is in ambient mode, + // which means it won't receive input events. + boolean mIsAmbientMode = false; + // Set to true to stop input during an Activity Transition. boolean mPausedForTransition = false; @@ -990,6 +994,10 @@ public final class ViewRootImpl implements ViewParent, } } + public void setIsAmbientMode(boolean ambient) { + mIsAmbientMode = ambient; + } + void setWindowStopped(boolean stopped) { if (mStopped != stopped) { mStopped = stopped; @@ -3704,7 +3712,7 @@ public final class ViewRootImpl implements ViewParent, return true; } else if ((!mAttachInfo.mHasWindowFocus && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) || mStopped - || (mPausedForTransition && !isBack(q.mEvent))) { + || mIsAmbientMode || (mPausedForTransition && !isBack(q.mEvent))) { // This is a focus event and the window doesn't currently have input focus or // has stopped. This could be an event that came back from the previous stage // but the window has lost focus or stopped in the meantime. @@ -5514,6 +5522,8 @@ public final class ViewRootImpl implements ViewParent, writer.println(mProcessInputEventsScheduled); writer.print(innerPrefix); writer.print("mTraversalScheduled="); writer.print(mTraversalScheduled); + writer.print(innerPrefix); writer.print("mIsAmbientMode="); + writer.print(mIsAmbientMode); if (mTraversalScheduled) { writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")"); } else { diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index b5e08ca..df3d850 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -348,7 +348,6 @@ public class LinearLayout extends ViewGroup { final int count = getVirtualChildCount(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); @@ -377,7 +376,7 @@ public class LinearLayout extends ViewGroup { */ private View getLastNonGoneChild() { for (int i = getVirtualChildCount() - 1; i >= 0; i--) { - View child = getVirtualChildAt(i); + final View child = getVirtualChildAt(i); if (child != null && child.getVisibility() != GONE) { return child; } @@ -390,7 +389,6 @@ public class LinearLayout extends ViewGroup { final boolean isLayoutRtl = isLayoutRtl(); for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child != null && child.getVisibility() != GONE) { if (hasDividerBeforeChildAt(i)) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); @@ -577,8 +575,9 @@ public class LinearLayout extends ViewGroup { * for an example.</p> * * @param index the child's index - * @return the child at the specified index + * @return the child at the specified index, may be {@code null} */ + @Nullable View getVirtualChildAt(int index) { return getChildAt(index); } @@ -659,7 +658,7 @@ public class LinearLayout extends ViewGroup { */ private boolean allViewsAreGoneBefore(int childIndex) { for (int i = childIndex - 1; i >= 0; i--) { - View child = getVirtualChildAt(i); + final View child = getVirtualChildAt(i); if (child != null && child.getVisibility() != GONE) { return false; } @@ -703,7 +702,6 @@ public class LinearLayout extends ViewGroup { // See how tall everyone is. Also remember max width. for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -822,7 +820,6 @@ public class LinearLayout extends ViewGroup { for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -938,7 +935,6 @@ public class LinearLayout extends ViewGroup { if (useLargestChild && heightMode != MeasureSpec.EXACTLY) { for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null || child.getVisibility() == View.GONE) { continue; } @@ -981,7 +977,7 @@ public class LinearLayout extends ViewGroup { MeasureSpec.EXACTLY); for (int i = 0; i< count; ++i) { final View child = getVirtualChildAt(i); - if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams()); if (lp.width == LayoutParams.MATCH_PARENT) { @@ -1047,7 +1043,6 @@ public class LinearLayout extends ViewGroup { // See how wide everyone is. Also remember max height. for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -1203,7 +1198,6 @@ public class LinearLayout extends ViewGroup { for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child == null) { mTotalLength += measureNullChild(i); continue; @@ -1361,7 +1355,6 @@ public class LinearLayout extends ViewGroup { if (useLargestChild && widthMode != MeasureSpec.EXACTLY) { for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); - if (child == null || child.getVisibility() == View.GONE) { continue; } @@ -1406,7 +1399,7 @@ public class LinearLayout extends ViewGroup { MeasureSpec.EXACTLY); for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); - if (child.getVisibility() != GONE) { + if (child != null && child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); if (lp.height == LayoutParams.MATCH_PARENT) { @@ -1666,9 +1659,8 @@ public class LinearLayout extends ViewGroup { } for (int i = 0; i < count; i++) { - int childIndex = start + dir * i; + final int childIndex = start + dir * i; final View child = getVirtualChildAt(childIndex); - if (child == null) { childLeft += measureNullChild(childIndex); } else if (child.getVisibility() != GONE) { diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java index 9130d9a..50569d7 100644 --- a/core/java/android/widget/OverScroller.java +++ b/core/java/android/widget/OverScroller.java @@ -18,7 +18,6 @@ package android.widget; import android.content.Context; import android.hardware.SensorManager; -import android.os.PowerManager; import android.util.Log; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; @@ -600,8 +599,6 @@ public class OverScroller { private static final int CUBIC = 1; private static final int BALLISTIC = 2; - private final PowerManager mPm; - static { float x_min = 0.0f; float y_min = 0.0f; @@ -646,7 +643,6 @@ public class OverScroller { * 39.37f // inch/meter * ppi * 0.84f; // look and feel tuning - mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); } void updateScroll(float q) { @@ -764,7 +760,6 @@ public class OverScroller { if (velocity != 0) { mDuration = mSplineDuration = getSplineFlingDuration(velocity); totalDistance = getSplineFlingDistance(velocity); - mPm.cpuBoost(mDuration * 1000); } mSplineDistance = (int) (totalDistance * Math.signum(velocity)); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 6c9c0e3..6a272e5 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -31,6 +31,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.Rect; @@ -55,6 +56,8 @@ import android.view.ViewGroup; import android.widget.AdapterView.OnItemClickListener; import libcore.util.Objects; +import com.android.internal.R; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -206,14 +209,22 @@ public class RemoteViews implements Parcelable, Filter { /** @hide */ public static class OnClickHandler { + + private int mEnterAnimationId; + public boolean onClickHandler(View view, PendingIntent pendingIntent, Intent fillInIntent) { try { // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? Context context = view.getContext(); - ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view, - 0, 0, - view.getMeasuredWidth(), view.getMeasuredHeight()); + ActivityOptions opts; + if (mEnterAnimationId != 0) { + opts = ActivityOptions.makeCustomAnimation(context, mEnterAnimationId, 0); + } else { + opts = ActivityOptions.makeScaleUpAnimation(view, + 0, 0, + view.getMeasuredWidth(), view.getMeasuredHeight()); + } context.startIntentSender( pendingIntent.getIntentSender(), fillInIntent, Intent.FLAG_ACTIVITY_NEW_TASK, @@ -228,6 +239,10 @@ public class RemoteViews implements Parcelable, Filter { } return true; } + + public void setEnterAnimationId(int enterAnimationId) { + mEnterAnimationId = enterAnimationId; + } } /** @@ -2767,11 +2782,31 @@ public class RemoteViews implements Parcelable, Filter { inflater.setFilter(this); result = inflater.inflate(rvToApply.getLayoutId(), parent, false); + loadTransitionOverride(context, handler); + rvToApply.performApply(result, parent, handler); return result; } + private static void loadTransitionOverride(Context context, + RemoteViews.OnClickHandler handler) { + if (handler != null && context.getResources().getBoolean( + com.android.internal.R.bool.config_overrideRemoteViewsActivityTransition)) { + TypedArray windowStyle = context.getTheme().obtainStyledAttributes( + com.android.internal.R.styleable.Window); + int windowAnimations = windowStyle.getResourceId( + com.android.internal.R.styleable.Window_windowAnimationStyle, 0); + TypedArray windowAnimationStyle = context.obtainStyledAttributes( + windowAnimations, com.android.internal.R.styleable.WindowAnimation); + handler.setEnterAnimationId(windowAnimationStyle.getResourceId( + com.android.internal.R.styleable. + WindowAnimation_activityOpenRemoteViewsEnterAnimation, 0)); + windowStyle.recycle(); + windowAnimationStyle.recycle(); + } + } + /** * Applies all of the actions to the provided view. * diff --git a/core/java/android/widget/Scroller.java b/core/java/android/widget/Scroller.java index a968eae..357c9c3 100644 --- a/core/java/android/widget/Scroller.java +++ b/core/java/android/widget/Scroller.java @@ -19,7 +19,6 @@ package android.widget; import android.content.Context; import android.hardware.SensorManager; import android.os.Build; -import android.os.PowerManager; import android.view.ViewConfiguration; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -109,8 +108,6 @@ public class Scroller { private float mDeceleration; private final float mPpi; - private final PowerManager mPm; - // A context-specific coefficient adjusted to physical values. private float mPhysicalCoeff; @@ -181,8 +178,6 @@ public class Scroller { mFlywheel = flywheel; mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning - - mPm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); } /** @@ -400,8 +395,6 @@ public class Scroller { mDeltaX = dx; mDeltaY = dy; mDurationReciprocal = 1.0f / (float) mDuration; - - mPm.cpuBoost(duration * 1000); } /** diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java index f7f9c91..22931fc 100644 --- a/core/java/android/widget/TableRow.java +++ b/core/java/android/widget/TableRow.java @@ -98,7 +98,7 @@ public class TableRow extends LinearLayout { * {@hide} */ void setColumnCollapsed(int columnIndex, boolean collapsed) { - View child = getVirtualChildAt(columnIndex); + final View child = getVirtualChildAt(columnIndex); if (child != null) { child.setVisibility(collapsed ? GONE : VISIBLE); } diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java index 4b31af0..e8dccab 100644 --- a/core/java/android/widget/Toast.java +++ b/core/java/android/widget/Toast.java @@ -18,6 +18,7 @@ package android.widget; import android.annotation.IntDef; import android.annotation.StringRes; +import android.app.ActivityManager; import android.app.INotificationManager; import android.app.ITransientNotification; import android.content.Context; @@ -405,14 +406,18 @@ public class Toast { ImageView appIcon = (ImageView) mView.findViewById(android.R.id.icon); if (appIcon != null) { - PackageManager pm = context.getPackageManager(); - Drawable icon = null; - try { - icon = pm.getApplicationIcon(packageName); - } catch (PackageManager.NameNotFoundException e) { - // nothing to do + ActivityManager am = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + if (!am.isPackageInForeground(packageName)) { + PackageManager pm = context.getPackageManager(); + Drawable icon = null; + try { + icon = pm.getApplicationIcon(packageName); + } catch (PackageManager.NameNotFoundException e) { + // nothing to do + } + appIcon.setImageDrawable(icon); } - appIcon.setImageDrawable(icon); } mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); // We can resolve the Gravity here by using the Locale for getting diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 3cddbf6..ba92f48 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -121,4 +122,18 @@ interface IBatteryStats { void setBatteryState(int status, int health, int plugType, int level, int temp, int volt); long getAwakeTimeBattery(); long getAwakeTimePlugged(); + + + /** @hide */ + byte[] getDockStatistics(); + /** @hide */ + ParcelFileDescriptor getDockStatisticsStream(); + /** @hide **/ + void resetStatistics(); + /** @hide **/ + void setDockBatteryState(int status, int health, int plugType, int level, int temp, int volt); + /** @hide **/ + long getAwakeTimeDockBattery(); + /** @hide **/ + long getAwakeTimeDockPlugged(); } diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index f178c8c..54a4e86 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.hardware.SensorManager; import android.net.ConnectivityManager; +import android.os.BatteryManager; import android.os.BatteryStats; import android.os.BatteryStats.Uid; import android.os.Bundle; @@ -61,15 +62,18 @@ public final class BatteryStatsHelper { private static final String TAG = BatteryStatsHelper.class.getSimpleName(); private static BatteryStats sStatsXfer; + private static BatteryStats sDockStatsXfer; private static Intent sBatteryBroadcastXfer; private static ArrayMap<File, BatteryStats> sFileXfer = new ArrayMap<>(); final private Context mContext; + final private BatteryManager mBatteryService; final private boolean mCollectBatteryBroadcast; final private boolean mWifiOnly; private IBatteryStats mBatteryInfo; private BatteryStats mStats; + private BatteryStats mDockStats; private Intent mBatteryBroadcast; private PowerProfile mPowerProfile; @@ -160,19 +164,28 @@ public final class BatteryStatsHelper { public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast, boolean wifiOnly) { mContext = context; + mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE)); mCollectBatteryBroadcast = collectBatteryBroadcast; mWifiOnly = wifiOnly; } public void storeStatsHistoryInFile(String fname) { + internalStoreStatsHistoryInFile(getStats(), fname); + } + + public void storeDockStatsHistoryInFile(String fname) { + internalStoreStatsHistoryInFile(getDockStats(), fname); + } + + public void internalStoreStatsHistoryInFile(BatteryStats stats, String fname) { synchronized (sFileXfer) { File path = makeFilePath(mContext, fname); - sFileXfer.put(path, this.getStats()); + sFileXfer.put(path, stats); FileOutputStream fout = null; try { fout = new FileOutputStream(path); Parcel hist = Parcel.obtain(); - getStats().writeToParcelWithoutUids(hist, 0); + stats.writeToParcelWithoutUids(hist, 0); byte[] histData = hist.marshall(); fout.write(histData); } catch (IOException e) { @@ -229,18 +242,38 @@ public final class BatteryStatsHelper { /** Clears the current stats and forces recreating for future use. */ public void clearStats() { mStats = null; + mDockStats = null; + } + + private void clearAllStats() { + clearStats(); + sStatsXfer = null; + sDockStatsXfer = null; + sBatteryBroadcastXfer = null; + for (File f : sFileXfer.keySet()) { + f.delete(); + } + sFileXfer.clear(); } public BatteryStats getStats() { if (mStats == null) { - load(); + loadStats(); } return mStats; } + public BatteryStats getDockStats() { + if (mDockStats == null) { + loadDockStats(); + } + return mDockStats; + } + public Intent getBatteryBroadcast() { if (mBatteryBroadcast == null && mCollectBatteryBroadcast) { - load(); + loadStats(); + loadDockStats(); } return mBatteryBroadcast; } @@ -257,6 +290,7 @@ public final class BatteryStatsHelper { public void create(Bundle icicle) { if (icicle != null) { mStats = sStatsXfer; + mDockStats = sDockStatsXfer; mBatteryBroadcast = sBatteryBroadcastXfer; } mBatteryInfo = IBatteryStats.Stub.asInterface( @@ -266,6 +300,7 @@ public final class BatteryStatsHelper { public void storeState() { sStatsXfer = mStats; + sDockStatsXfer = mDockStats; sBatteryBroadcastXfer = mBatteryBroadcast; } @@ -321,6 +356,7 @@ public final class BatteryStatsHelper { long rawUptimeUs) { // Initialize mStats if necessary. getStats(); + getDockStats(); mMaxPower = 0; mMaxRealPower = 0; @@ -739,7 +775,7 @@ public final class BatteryStatsHelper { } } - private void load() { + private void loadStats() { if (mBatteryInfo == null) { return; } @@ -750,6 +786,26 @@ public final class BatteryStatsHelper { } } + private void loadDockStats() { + if (mBatteryInfo == null) { + return; + } + if (mBatteryService.isDockBatterySupported()) { + mDockStats = getDockStats(mBatteryInfo); + } else { + mDockStats = null; + } + } + + public void resetStatistics() { + try { + clearAllStats(); + mBatteryInfo.resetStatistics(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException:", e); + } + } + private static BatteryStatsImpl getStats(IBatteryStats service) { try { ParcelFileDescriptor pfd = service.getStatisticsStream(); @@ -772,4 +828,27 @@ public final class BatteryStatsHelper { } return new BatteryStatsImpl(); } + + private static BatteryStatsImpl getDockStats(IBatteryStats service) { + try { + ParcelFileDescriptor pfd = service.getDockStatisticsStream(); + if (pfd != null) { + FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd); + try { + byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor())); + Parcel parcel = Parcel.obtain(); + parcel.unmarshall(data, 0, data.length); + parcel.setDataPosition(0); + BatteryStatsImpl stats = com.android.internal.os.DockBatteryStatsImpl.CREATOR + .createFromParcel(parcel); + return stats; + } catch (IOException e) { + Log.w(TAG, "Unable to read statistics stream", e); + } + } + } catch (RemoteException e) { + Log.w(TAG, "RemoteException:", e); + } + return new BatteryStatsImpl(); + } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 64b7768..d0a169e 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006-2007 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -91,7 +92,7 @@ import java.util.concurrent.locks.ReentrantLock; * battery life. All times are represented in microseconds except where indicated * otherwise. */ -public final class BatteryStatsImpl extends BatteryStats { +public class BatteryStatsImpl extends BatteryStats { private static final String TAG = "BatteryStatsImpl"; private static final boolean DEBUG = false; public static final boolean DEBUG_ENERGY = false; @@ -105,7 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 132 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 133 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -1968,8 +1969,14 @@ public final class BatteryStatsImpl extends BatteryStats { private int buildBatteryLevelInt(HistoryItem h) { return ((((int)h.batteryLevel)<<25)&0xfe000000) - | ((((int)h.batteryTemperature)<<14)&0x01ff8000) - | ((((int)h.batteryVoltage)<<1)&0x00007fff); + | ((((int)h.batteryTemperature)<<15)&0x01ff8000) + | ((((int)h.batteryVoltage)<<1)&0x00007ffe); + } + + private void readBatteryLevelInt(int batteryLevelInt, HistoryItem out) { + out.batteryLevel = (byte)((batteryLevelInt & 0xfe000000) >>> 25); + out.batteryTemperature = (short)((batteryLevelInt & 0x01ff8000) >>> 15); + out.batteryVoltage = (char)((batteryLevelInt & 0x00007ffe) >>> 1); } private int buildStateInt(HistoryItem h) { @@ -2110,9 +2117,7 @@ public final class BatteryStatsImpl extends BatteryStats { final int batteryLevelInt; if ((firstToken&DELTA_BATTERY_LEVEL_FLAG) != 0) { batteryLevelInt = src.readInt(); - cur.batteryLevel = (byte)((batteryLevelInt>>25)&0x7f); - cur.batteryTemperature = (short)((batteryLevelInt<<7)>>21); - cur.batteryVoltage = (char)(batteryLevelInt&0x3fff); + readBatteryLevelInt(batteryLevelInt, cur); cur.numReadInts += 1; if (DEBUG) Slog.i(TAG, "READ DELTA: batteryToken=0x" + Integer.toHexString(batteryLevelInt) @@ -6839,13 +6844,13 @@ public final class BatteryStatsImpl extends BatteryStats { public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { if (systemDir != null) { - mFile = new JournaledFile(new File(systemDir, "batterystats.bin"), - new File(systemDir, "batterystats.bin.tmp")); + mFile = new JournaledFile(new File(systemDir, getStatsName() + ".bin"), + new File(systemDir, getStatsName() + ".bin.tmp")); } else { mFile = null; } - mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin")); - mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml")); + mCheckinFile = new AtomicFile(new File(systemDir, getStatsName() + "-checkin.bin")); + mDailyFile = new AtomicFile(new File(systemDir, getStatsName () + "-daily.xml")); mExternalSync = externalSync; mHandler = new MyHandler(handler.getLooper()); mStartCount++; @@ -6921,6 +6926,16 @@ public final class BatteryStatsImpl extends BatteryStats { readFromParcel(p); } + /** @hide */ + protected String getStatsName() { + return "batterystats"; + } + + /** @hide */ + protected String getLogName() { + return "BatteryStats"; + } + public void setPowerProfile(PowerProfile profile) { synchronized (this) { mPowerProfile = profile; @@ -7699,26 +7714,35 @@ public final class BatteryStatsImpl extends BatteryStats { } final Uid u = getUidStatsLocked(mapUid(entry.uid)); - u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, - entry.rxPackets); - u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, - entry.txPackets); - rxPackets.put(u.getUid(), entry.rxPackets); - txPackets.put(u.getUid(), entry.txPackets); + if (entry.rxBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, + entry.rxPackets); + mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( + entry.rxPackets); - // Sum the total number of packets so that the Rx Power and Tx Power can - // be evenly distributed amongst the apps. - totalRxPackets += entry.rxPackets; - totalTxPackets += entry.txPackets; + rxPackets.put(u.getUid(), entry.rxPackets); - mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxBytes); - mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txBytes); - mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked( - entry.rxPackets); - mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( - entry.txPackets); + // Sum the total number of packets so that the Rx Power can + // be evenly distributed amongst the apps. + totalRxPackets += entry.rxPackets; + } + + if (entry.txBytes != 0) { + u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes, + entry.txPackets); + mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txBytes); + mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked( + entry.txPackets); + + txPackets.put(u.getUid(), entry.txPackets); + + // Sum the total number of packets so that the Tx Power can + // be evenly distributed amongst the apps. + totalTxPackets += entry.txPackets; + } } } @@ -8434,7 +8458,13 @@ public final class BatteryStatsImpl extends BatteryStats { public void setBatteryStateLocked(int status, int health, int plugType, int level, int temp, int volt) { - final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; + // We need to add a extra check over the status because of dock batteries + // PlugType doesn't means that the dock battery is charging (some devices + // doesn't charge under dock usb) + boolean onBattery = plugType == BATTERY_PLUGGED_NONE && + (status != BatteryManager.BATTERY_STATUS_CHARGING || + status != BatteryManager.BATTERY_STATUS_FULL); + final long uptime = SystemClock.uptimeMillis(); final long elapsedRealtime = SystemClock.elapsedRealtime(); if (!mHaveBatteryLevel) { diff --git a/core/java/com/android/internal/os/DockBatteryStatsImpl.java b/core/java/com/android/internal/os/DockBatteryStatsImpl.java new file mode 100644 index 0000000..6099ad2 --- /dev/null +++ b/core/java/com/android/internal/os/DockBatteryStatsImpl.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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.os; + +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; + +import java.io.File; + +public final class DockBatteryStatsImpl extends BatteryStatsImpl { + public DockBatteryStatsImpl() { + super(); + } + + public DockBatteryStatsImpl(Parcel p) { + super(p); + } + + public DockBatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) { + super(systemDir, handler, externalSync); + } + + protected String getStatsName() { + return "dockbatterystats"; + } + + protected String getLogName() { + return "DockBatteryStats"; + } + + public static final Parcelable.Creator<DockBatteryStatsImpl> CREATOR = + new Parcelable.Creator<DockBatteryStatsImpl>() { + public DockBatteryStatsImpl createFromParcel(Parcel in) { + return new DockBatteryStatsImpl(in); + } + + public DockBatteryStatsImpl[] newArray(int size) { + return new DockBatteryStatsImpl[size]; + } + }; +} diff --git a/core/java/com/android/internal/os/KernelCpuSpeedReader.java b/core/java/com/android/internal/os/KernelCpuSpeedReader.java index 5b776ac..3f6ebb9 100644 --- a/core/java/com/android/internal/os/KernelCpuSpeedReader.java +++ b/core/java/com/android/internal/os/KernelCpuSpeedReader.java @@ -16,8 +16,11 @@ package com.android.internal.os; import android.text.TextUtils; +import android.system.OsConstants; import android.util.Slog; +import libcore.io.Libcore; + import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -29,7 +32,7 @@ import java.util.Arrays; * * freq time * - * where time is measured in 1/100 seconds. + * where time is measured in jiffies. */ public class KernelCpuSpeedReader { private static final String TAG = "KernelCpuSpeedReader"; @@ -38,6 +41,9 @@ public class KernelCpuSpeedReader { private final long[] mLastSpeedTimes; private final long[] mDeltaSpeedTimes; + // How long a CPU jiffy is in milliseconds. + private final long mJiffyMillis; + /** * @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read. */ @@ -46,6 +52,8 @@ public class KernelCpuSpeedReader { cpuNumber); mLastSpeedTimes = new long[numSpeedSteps]; mDeltaSpeedTimes = new long[numSpeedSteps]; + long jiffyHz = Libcore.os.sysconf(OsConstants._SC_CLK_TCK); + mJiffyMillis = 1000/jiffyHz; } /** @@ -62,8 +70,7 @@ public class KernelCpuSpeedReader { splitter.setString(line); Long.parseLong(splitter.next()); - // The proc file reports time in 1/100 sec, so convert to milliseconds. - long time = Long.parseLong(splitter.next()) * 10; + long time = Long.parseLong(splitter.next()) * mJiffyMillis; if (time < mLastSpeedTimes[speedIndex]) { // The stats reset when the cpu hotplugged. That means that the time // we read is offset from 0, so the time is the delta. diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java index bf97f1f..d831902 100644 --- a/core/java/com/android/internal/os/ProcessCpuTracker.java +++ b/core/java/com/android/internal/os/ProcessCpuTracker.java @@ -67,10 +67,10 @@ public class ProcessCpuTracker { static final int PROCESS_STAT_UTIME = 2; static final int PROCESS_STAT_STIME = 3; - /** Stores user time and system time in 100ths of a second. */ + /** Stores user time and system time in jiffies. */ private final long[] mProcessStatsData = new long[4]; - /** Stores user time and system time in 100ths of a second. Used for + /** Stores user time and system time in jiffies. Used for * public API to retrieve CPU use for a process. Must lock while in use. */ private final long[] mSinglePidStatsData = new long[4]; diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java index f81658e..3377189 100644 --- a/core/java/com/android/internal/os/RuntimeInit.java +++ b/core/java/com/android/internal/os/RuntimeInit.java @@ -19,6 +19,7 @@ package com.android.internal.os; import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.ApplicationErrorReport; +import android.content.res.ThemeConfig; import android.os.Build; import android.os.Debug; import android.os.IBinder; @@ -83,6 +84,10 @@ public class RuntimeInit { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); + final ThemeConfig themeConfig = + ActivityManagerNative.getDefault().getConfiguration().themeConfig; + message.append("\nTheme: ").append(themeConfig == null ? + ThemeConfig.SYSTEM_DEFAULT : themeConfig); Clog_e(TAG, message.toString(), e); } diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java index 447292c..be78a12 100644 --- a/core/java/com/android/internal/util/StateMachine.java +++ b/core/java/com/android/internal/util/StateMachine.java @@ -1879,6 +1879,33 @@ public class StateMachine { } /** + * Check if there are any pending messages with code 'what' in deferred messages queue. + */ + protected final boolean hasDeferredMessages(int what) { + SmHandler smh = mSmHandler; + if (smh == null) return false; + + Iterator<Message> iterator = smh.mDeferredMessages.iterator(); + while (iterator.hasNext()) { + Message msg = iterator.next(); + if (msg.what == what) return true; + } + + return false; + } + + /** + * Check if there are any pending posts of messages with code 'what' in + * the message queue. This does NOT check messages in deferred message queue. + */ + protected final boolean hasMessages(int what) { + SmHandler smh = mSmHandler; + if (smh == null) return false; + + return smh.hasMessages(what); + } + + /** * Validate that the message was sent by * {@link StateMachine#quit} or {@link StateMachine#quitNow}. * */ diff --git a/core/java/com/android/internal/util/cm/ImageUtils.java b/core/java/com/android/internal/util/cm/ImageUtils.java deleted file mode 100644 index 73189a3..0000000 --- a/core/java/com/android/internal/util/cm/ImageUtils.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (C) 2013-2014 The CyanogenMod Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.util.cm; - -import android.app.WallpaperManager; -import android.content.Context; -import android.content.pm.ThemeUtils; -import android.content.res.AssetManager; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Point; -import android.net.Uri; -import android.provider.ThemesContract; -import android.provider.ThemesContract.ThemesColumns; -import android.text.TextUtils; -import android.util.Log; -import android.webkit.URLUtil; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; - -import libcore.io.IoUtils; - -public class ImageUtils { - private static final String TAG = ImageUtils.class.getSimpleName(); - - private static final String ASSET_URI_PREFIX = "file:///android_asset/"; - private static final int DEFAULT_IMG_QUALITY = 100; - - /** - * Gets the Width and Height of the image - * - * @param inputStream The input stream of the image - * - * @return A point structure that holds the Width and Height (x and y)/*" - */ - public static Point getImageDimension(InputStream inputStream) { - if (inputStream == null) { - throw new IllegalArgumentException("'inputStream' cannot be null!"); - } - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeStream(inputStream, null, options); - Point point = new Point(options.outWidth,options.outHeight); - return point; - } - - /** - * Crops the input image and returns a new InputStream of the cropped area - * - * @param inputStream The input stream of the image - * @param imageWidth Width of the input image - * @param imageHeight Height of the input image - * @param inputStream Desired Width - * @param inputStream Desired Width - * - * @return a new InputStream of the cropped area/*" - */ - public static InputStream cropImage(InputStream inputStream, int imageWidth, int imageHeight, - int outWidth, int outHeight) throws IllegalArgumentException { - if (inputStream == null){ - throw new IllegalArgumentException("inputStream cannot be null"); - } - - if (imageWidth <= 0 || imageHeight <= 0) { - throw new IllegalArgumentException( - String.format("imageWidth and imageHeight must be > 0: imageWidth=%d" + - " imageHeight=%d", imageWidth, imageHeight)); - } - - if (outWidth <= 0 || outHeight <= 0) { - throw new IllegalArgumentException( - String.format("outWidth and outHeight must be > 0: outWidth=%d" + - " outHeight=%d", imageWidth, outHeight)); - } - - int scaleDownSampleSize = Math.min(imageWidth / outWidth, imageHeight / outHeight); - if (scaleDownSampleSize > 0) { - imageWidth /= scaleDownSampleSize; - imageHeight /= scaleDownSampleSize; - } else { - float ratio = (float) outWidth / outHeight; - if (imageWidth < imageHeight * ratio) { - outWidth = imageWidth; - outHeight = (int) (outWidth / ratio); - } else { - outHeight = imageHeight; - outWidth = (int) (outHeight * ratio); - } - } - int left = (imageWidth - outWidth) / 2; - int top = (imageHeight - outHeight) / 2; - InputStream compressed = null; - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - if (scaleDownSampleSize > 1) { - options.inSampleSize = scaleDownSampleSize; - } - Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); - if (bitmap == null) { - return null; - } - Bitmap cropped = Bitmap.createBitmap(bitmap, left, top, outWidth, outHeight); - ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); - if (cropped.compress(Bitmap.CompressFormat.PNG, DEFAULT_IMG_QUALITY, tmpOut)) { - byte[] outByteArray = tmpOut.toByteArray(); - compressed = new ByteArrayInputStream(outByteArray); - } - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } - return compressed; - } - - /** - * Crops the lock screen image and returns a new InputStream of the cropped area - * - * @param pkgName Name of the theme package - * @param context The context - * - * @return a new InputStream of the cropped image/*" - */ - public static InputStream getCroppedKeyguardStream(String pkgName, Context context) - throws IllegalArgumentException { - if (TextUtils.isEmpty(pkgName)) { - throw new IllegalArgumentException("'pkgName' cannot be null or empty!"); - } - if (context == null) { - throw new IllegalArgumentException("'context' cannot be null!"); - } - - InputStream cropped = null; - InputStream stream = null; - try { - stream = getOriginalKeyguardStream(pkgName, context); - if (stream == null) { - return null; - } - Point point = getImageDimension(stream); - IoUtils.closeQuietly(stream); - if (point == null || point.x == 0 || point.y == 0) { - return null; - } - WallpaperManager wm = WallpaperManager.getInstance(context); - int outWidth = wm.getDesiredMinimumWidth(); - int outHeight = wm.getDesiredMinimumHeight(); - stream = getOriginalKeyguardStream(pkgName, context); - if (stream == null) { - return null; - } - cropped = cropImage(stream, point.x, point.y, outWidth, outHeight); - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } finally { - IoUtils.closeQuietly(stream); - } - return cropped; - } - - /** - * Crops the wallpaper image and returns a new InputStream of the cropped area - * - * @param pkgName Name of the theme package - * @param context The context - * - * @return a new InputStream of the cropped image/*" - */ - public static InputStream getCroppedWallpaperStream(String pkgName, long wallpaperId, - Context context) { - if (TextUtils.isEmpty(pkgName)) { - throw new IllegalArgumentException("'pkgName' cannot be null or empty!"); - } - if (context == null) { - throw new IllegalArgumentException("'context' cannot be null!"); - } - - InputStream cropped = null; - InputStream stream = null; - try { - stream = getOriginalWallpaperStream(pkgName, wallpaperId, context); - if (stream == null) { - return null; - } - Point point = getImageDimension(stream); - IoUtils.closeQuietly(stream); - if (point == null || point.x == 0 || point.y == 0) { - return null; - } - WallpaperManager wm = WallpaperManager.getInstance(context); - int outWidth = wm.getDesiredMinimumWidth(); - int outHeight = wm.getDesiredMinimumHeight(); - stream = getOriginalWallpaperStream(pkgName, wallpaperId, context); - if (stream == null) { - return null; - } - cropped = cropImage(stream, point.x, point.y, outWidth, outHeight); - } catch (Exception e) { - Log.e(TAG, "Exception " + e); - } finally { - IoUtils.closeQuietly(stream); - } - return cropped; - } - - private static InputStream getOriginalKeyguardStream(String pkgName, Context context) { - if (TextUtils.isEmpty(pkgName) || context == null) { - return null; - } - - InputStream inputStream = null; - try { - //Get input WP stream from the theme - Context themeCtx = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - String wpPath = ThemeUtils.getLockscreenWallpaperPath(assetManager); - if (wpPath == null) { - Log.w(TAG, "Not setting lockscreen wp because wallpaper file was not found."); - } else { - inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx, - ASSET_URI_PREFIX + wpPath); - } - } catch (Exception e) { - Log.e(TAG, "There was an error setting lockscreen wp for pkg " + pkgName, e); - } - return inputStream; - } - - private static InputStream getOriginalWallpaperStream(String pkgName, long componentId, - Context context) { - String wpPath; - if (TextUtils.isEmpty(pkgName) || context == null) { - return null; - } - - InputStream inputStream = null; - String selection = ThemesContract.ThemesColumns.PKG_NAME + "= ?"; - String[] selectionArgs = {pkgName}; - Cursor c = context.getContentResolver().query(ThemesColumns.CONTENT_URI, - null, selection, - selectionArgs, null); - if (c == null || c.getCount() < 1) { - if (c != null) c.close(); - return null; - } else { - c.moveToFirst(); - } - - try { - Context themeContext = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - boolean isLegacyTheme = c.getInt( - c.getColumnIndex(ThemesColumns.IS_LEGACY_THEME)) == 1; - String wallpaper = c.getString( - c.getColumnIndex(ThemesColumns.WALLPAPER_URI)); - if (wallpaper != null) { - if (URLUtil.isAssetUrl(wallpaper)) { - inputStream = ThemeUtils.getInputStreamFromAsset(themeContext, wallpaper); - } else { - inputStream = context.getContentResolver().openInputStream( - Uri.parse(wallpaper)); - } - } else { - // try and get the wallpaper directly from the apk if the URI was null - Context themeCtx = context.createPackageContext(pkgName, - Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - wpPath = queryWpPathFromComponentId(context, pkgName, componentId); - if (wpPath == null) wpPath = ThemeUtils.getWallpaperPath(assetManager); - if (wpPath == null) { - Log.e(TAG, "Not setting wp because wallpaper file was not found."); - } else { - inputStream = ThemeUtils.getInputStreamFromAsset(themeCtx, - ASSET_URI_PREFIX + wpPath); - } - } - } catch (Exception e) { - Log.e(TAG, "getWallpaperStream: " + e); - } finally { - c.close(); - } - - return inputStream; - } - - private static String queryWpPathFromComponentId(Context context, String pkgName, - long componentId) { - String wpPath = null; - String[] projection = new String[] { ThemesContract.PreviewColumns.COL_VALUE }; - String selection = ThemesColumns.PKG_NAME + "=? AND " + - ThemesContract.PreviewColumns.COMPONENT_ID + "=? AND " + - ThemesContract.PreviewColumns.COL_KEY + "=?"; - String[] selectionArgs = new String[] { - pkgName, - Long.toString(componentId), - ThemesContract.PreviewColumns.WALLPAPER_FULL - }; - - Cursor c = context.getContentResolver() - .query(ThemesContract.PreviewColumns.COMPONENTS_URI, - projection, selection, selectionArgs, null); - if (c != null) { - try { - if (c.moveToFirst()) { - int valIdx = c.getColumnIndex(ThemesContract.PreviewColumns.COL_VALUE); - wpPath = c.getString(valIdx); - } - } catch(Exception e) { - Log.e(TAG, "Could not get wallpaper path", e); - } finally { - c.close(); - } - } - return wpPath; - } -} - diff --git a/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java b/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java deleted file mode 100644 index 01cfdea..0000000 --- a/core/java/com/android/internal/util/gesture/EdgeGesturePosition.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.android.internal.util.gesture; - -/** - * Defines the positions in which gestures may be recognized by the - * edge gesture service. - * This defines an index and an flag for each position. - */ -public enum EdgeGesturePosition { - LEFT(0, 0), - BOTTOM(1, 1), - RIGHT(2, 1), - TOP(3, 0); - - EdgeGesturePosition(int index, int factor) { - INDEX = index; - FLAG = (0x01<<index); - FACTOR = factor; - } - - public final int INDEX; - public final int FLAG; - /** - * This is 1 when the position is not at the axis (like {@link EdgeGesturePosition.RIGHT} is - * at {@code Layout.getWidth()} not at {@code 0}). - */ - public final int FACTOR; -} diff --git a/core/java/com/android/internal/util/gesture/EdgeServiceConstants.java b/core/java/com/android/internal/util/gesture/EdgeServiceConstants.java deleted file mode 100644 index 4360086..0000000 --- a/core/java/com/android/internal/util/gesture/EdgeServiceConstants.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.android.internal.util.gesture; - -/** - * Constants needed for the edge gesture service. - * - * @see com.android.internal.util.gesture.EdgeGesturePosition - */ -public final class EdgeServiceConstants { - - private EdgeServiceConstants() { - // no object allowed - } - - /** - * Mask for coding positions within the flags of - * {@code updateEdgeGestureActivationListener()}. - * <p> - * Positions are specified by {@code EdgeGesturePosition.FLAG}. - */ - public static final int POSITION_MASK = 0x0000001f; - - /** - * Mask for coding sensitivity within the flags of - * {@code updateEdgeGestureActivationListener()}. - * <p> - * Sensitivity influences the speed of the swipe, the trigger area, and trigger distance that - * is needed to activate the edge gesture. - */ - public static final int SENSITIVITY_MASK = 0x70000000; - - /** - * Number of bits to shift left, to get a integer within the {@link #SENSITIVITY_MASK}. - */ - public static final int SENSITIVITY_SHIFT = 28; - - /** - * No sensitivity specified at all, the service may choose a sensitivity level on its own. - */ - public static final int SENSITIVITY_NONE = 0; - - /** - * Default sensitivity, picked by the edge gesture service automatically. - */ - public static final int SENSITIVITY_DEFAULT = 2; - - /** - * Lowest valid sensitivity value. - */ - public static final int SENSITIVITY_LOWEST = 1; - - /** - * Highest sensitivity value. - */ - public static final int SENSITIVITY_HIGHEST = 4; - - /** - * Do not cut 10% area on th edges - */ - public static final int UNRESTRICTED = 0x10; - - /** - * This listener does not likes enabling/disabling filter - * because it interrupt in motion events. - */ - public static final int LONG_LIVING = 0x20; - -} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index be827a4..d9c2a92 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -64,6 +64,11 @@ public class LockPatternUtils { private static final boolean DEBUG = false; /** + * The key to identify when the lock pattern enabled flag is being acccessed for legacy reasons. + */ + public static final String LEGACY_LOCK_PATTERN_ENABLED = "legacy_lock_pattern_enabled"; + + /** * The number of incorrect attempts before which we fall back on an alternative * method of verifying the user, and resetting their lock pattern. */ @@ -1011,6 +1016,19 @@ public class LockPatternUtils { return isLockPatternEnabled(getKeyguardStoredPasswordQuality(userId), userId); } + @Deprecated + public boolean isLegacyLockPatternEnabled(int userId) { + // Note: this value should default to {@code true} to avoid any reset that might result. + // We must use a special key to read this value, since it will by default return the value + // based on the new logic. + return getBoolean(LEGACY_LOCK_PATTERN_ENABLED, true, userId); + } + + @Deprecated + public void setLegacyLockPatternEnabled(int userId) { + setBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, true, userId); + } + private boolean isLockPatternEnabled(int mode, int userId) { return mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING && savedPatternExists(userId); diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java index 35ed63b..d88f479 100644 --- a/core/java/com/android/internal/widget/SwipeDismissLayout.java +++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java @@ -89,14 +89,21 @@ public class SwipeDismissLayout extends FrameLayout { } }; private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { + private Runnable mRunnable = new Runnable() { + @Override + public void run() { + if (mDismissed) { + dismiss(); + } else { + cancel(); + } + resetMembers(); + } + }; + @Override public void onReceive(Context context, Intent intent) { - if (mDismissed) { - dismiss(); - } else { - cancel(); - } - resetMembers(); + post(mRunnable); } }; private IntentFilter mScreenOffFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF); |