diff options
Diffstat (limited to 'core/java/android')
22 files changed, 372 insertions, 131 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 4b705dd..fdb992a 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5586,6 +5586,16 @@ public class Activity extends ContextThemeWrapper } /** + * @hide + */ + public void dispatchEnterAnimationComplete() { + onEnterAnimationComplete(); + if (getWindow() != null && getWindow().getDecorView() != null) { + getWindow().getDecorView().getViewTreeObserver().dispatchOnEnterAnimationComplete(); + } + } + + /** * Adjust the current immersive mode setting. * * Note that changing this value will have no effect on the activity's diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 2a17fa6..d56dc1e 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -23,8 +23,8 @@ package android.app; */ public abstract class ActivityManagerInternal { // Called by the power manager. - public abstract void goingToSleep(); - public abstract void wakingUp(); + public abstract void onWakefulnessChanged(int wakefulness); + public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs, String processName, String abiOverride, int uid, Runnable crashHandler); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index dd49009..fe7b727 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2519,7 +2519,7 @@ public final class ActivityThread { private void handleEnterAnimationComplete(IBinder token) { ActivityClientRecord r = mActivities.get(token); if (r != null) { - r.activity.onEnterAnimationComplete(); + r.activity.dispatchEnterAnimationComplete(); } } diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 1e1a613..1b499cc 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1609,6 +1609,18 @@ final class ApplicationPackageManager extends PackageManager { return null; } + /** + * @hide + */ + @Override + public boolean isUpgrade() { + try { + return mPM.isUpgrade(); + } catch (RemoteException e) { + return false; + } + } + @Override public PackageInstaller getPackageInstaller() { synchronized (mLock) { diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 5564af7..c262bae 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -465,7 +465,8 @@ public final class BluetoothAdapter { if (getState() != STATE_ON) { return null; } - if (!isMultipleAdvertisementSupported()) { + if (!isMultipleAdvertisementSupported() && !isPeripheralModeSupported()) { + Log.e(TAG, "bluetooth le advertising not supported"); return null; } synchronized(mLock) { @@ -918,6 +919,21 @@ public final class BluetoothAdapter { } /** + * Returns whether peripheral mode is supported. + * + * @hide + */ + public boolean isPeripheralModeSupported() { + if (getState() != STATE_ON) return false; + try { + return mService.isPeripheralModeSupported(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get peripheral mode capability: ", e); + } + return false; + } + + /** * Return true if offloaded filters are supported * * @return true if chipset supports on-chip filtering @@ -1429,7 +1445,7 @@ public final class BluetoothAdapter { if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); synchronized (mManagerCallback) { mService = null; - mLeScanClients.clear(); + if (mLeScanClients != null) mLeScanClients.clear(); if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index cf2a343..992f601 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -92,6 +92,7 @@ interface IBluetooth boolean configHciSnoopLog(boolean enable); boolean isMultiAdvertisementSupported(); + boolean isPeripheralModeSupported(); boolean isOffloadedFilteringSupported(); boolean isOffloadedScanBatchingSupported(); boolean isActivityAndEnergyReportingSupported(); diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index d468508..a019d5c 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -111,7 +111,8 @@ public final class BluetoothLeAdvertiser { if (callback == null) { throw new IllegalArgumentException("callback cannot be null"); } - if (!mBluetoothAdapter.isMultipleAdvertisementSupported()) { + if (!mBluetoothAdapter.isMultipleAdvertisementSupported() && + !mBluetoothAdapter.isPeripheralModeSupported()) { postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED); return; diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index a57c3ca..93ea299 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -51,6 +51,7 @@ public final class BluetoothLeScanner { private static final String TAG = "BluetoothLeScanner"; private static final boolean DBG = true; + private static final boolean VDBG = false; private final IBluetoothManager mBluetoothManager; private final Handler mHandler; @@ -317,7 +318,7 @@ public final class BluetoothLeScanner { */ @Override public void onScanResult(final ScanResult scanResult) { - if (DBG) Log.d(TAG, "onScanResult() - " + scanResult.toString()); + if (VDBG) Log.d(TAG, "onScanResult() - " + scanResult.toString()); // Check null in case the scan has been stopped synchronized (this) { @@ -346,7 +347,7 @@ public final class BluetoothLeScanner { @Override public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) { - if (DBG) { + if (VDBG) { Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + " " + scanResult.toString()); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c37534a..0dc86ad 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -436,6 +436,7 @@ interface IPackageManager { boolean isFirstBoot(); boolean isOnlyCoreApps(); + boolean isUpgrade(); void setPermissionEnforced(String permission, boolean enforced); boolean isPermissionEnforced(String permission); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e519163..edd0d2a0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3867,6 +3867,13 @@ public abstract class PackageManager { public abstract VerifierDeviceIdentity getVerifierDeviceIdentity(); /** + * Returns true if the device is upgrading, such as first boot after OTA. + * + * @hide + */ + public abstract boolean isUpgrade(); + + /** * Return interface that offers the ability to install, upgrade, and remove * applications on the device. */ diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java index e0f1b3a..4ae3825 100644 --- a/core/java/android/content/res/ResourcesKey.java +++ b/core/java/android/content/res/ResourcesKey.java @@ -62,10 +62,15 @@ public final class ResourcesKey { return false; } ResourcesKey peer = (ResourcesKey) obj; - if (mResDir != peer.mResDir) { - if (mResDir == null || peer.mResDir == null) { - return false; - } else if (!mResDir.equals(peer.mResDir)) { + + if ((mResDir == null) && (peer.mResDir != null)) { + return false; + } + if ((mResDir != null) && (peer.mResDir == null)) { + return false; + } + if ((mResDir != null) && (peer.mResDir != null)) { + if (!mResDir.equals(peer.mResDir)) { return false; } } diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 8447dde..bb162153 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -172,9 +172,12 @@ public abstract class DisplayManagerInternal { // If true, enables automatic brightness control. public boolean useAutoBrightness; - //If true, scales the brightness to half of desired. + // If true, scales the brightness to half of desired. public boolean lowPowerMode; + // If true, applies a brightness boost. + public boolean boostScreenBrightness; + // If true, prevents the screen from completely turning on if it is currently off. // The display does not enter a "ready" state if this flag is true and screen on is // blocked. The window manager policy blocks screen on while it prepares the keyguard to @@ -216,6 +219,7 @@ public abstract class DisplayManagerInternal { useAutoBrightness = other.useAutoBrightness; blockScreenOn = other.blockScreenOn; lowPowerMode = other.lowPowerMode; + boostScreenBrightness = other.boostScreenBrightness; dozeScreenBrightness = other.dozeScreenBrightness; dozeScreenState = other.dozeScreenState; } @@ -235,6 +239,7 @@ public abstract class DisplayManagerInternal { && useAutoBrightness == other.useAutoBrightness && blockScreenOn == other.blockScreenOn && lowPowerMode == other.lowPowerMode + && boostScreenBrightness == other.boostScreenBrightness && dozeScreenBrightness == other.dozeScreenBrightness && dozeScreenState == other.dozeScreenState; } @@ -253,6 +258,7 @@ public abstract class DisplayManagerInternal { + ", useAutoBrightness=" + useAutoBrightness + ", blockScreenOn=" + blockScreenOn + ", lowPowerMode=" + lowPowerMode + + ", boostScreenBrightness=" + boostScreenBrightness + ", dozeScreenBrightness=" + dozeScreenBrightness + ", dozeScreenState=" + Display.stateToString(dozeScreenState); } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 53f9fcd..1efe478 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -19,16 +19,7 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import android.util.Log; - import java.lang.IllegalArgumentException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; /** * This class represents the capabilities of a network. This is used both to specify @@ -36,15 +27,12 @@ import java.util.Set; * * Note that this replaces the old {@link ConnectivityManager#TYPE_MOBILE} method * of network selection. Rather than indicate a need for Wi-Fi because an application - * needs high bandwidth and risk obselence when a new, fast network appears (like LTE), + * needs high bandwidth and risk obsolescence when a new, fast network appears (like LTE), * the application should specify it needs high bandwidth. Similarly if an application * needs an unmetered network for a bulk transfer it can specify that rather than assuming * all cellular based connections are metered and all Wi-Fi based connections are not. */ public final class NetworkCapabilities implements Parcelable { - private static final String TAG = "NetworkCapabilities"; - private static final boolean DBG = false; - /** * @hide */ @@ -541,9 +529,11 @@ public final class NetworkCapabilities implements Parcelable { (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17)); } + @Override public int describeContents() { return 0; } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(mNetworkCapabilities); dest.writeLong(mTransportTypes); @@ -553,6 +543,7 @@ public final class NetworkCapabilities implements Parcelable { } public static final Creator<NetworkCapabilities> CREATOR = new Creator<NetworkCapabilities>() { + @Override public NetworkCapabilities createFromParcel(Parcel in) { NetworkCapabilities netCap = new NetworkCapabilities(); @@ -563,11 +554,13 @@ public final class NetworkCapabilities implements Parcelable { netCap.mNetworkSpecifier = in.readString(); return netCap; } + @Override public NetworkCapabilities[] newArray(int size) { return new NetworkCapabilities[size]; } }; + @Override public String toString() { int[] types = getTransportTypes(); String transports = (types.length > 0 ? " Transports: " : ""); diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 182dbee..ec30684 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -50,6 +50,7 @@ interface IPowerManager void setStayOnSetting(int val); void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs); + void boostScreenBrightness(long time); // temporarily overrides the screen brightness settings to allow the user to // see the effect of a settings change without applying it immediately diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 3b6ce53..8307d9b 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -669,6 +669,28 @@ public final class PowerManager { } /** + * Boosts the brightness of the screen to maximum for a predetermined + * period of time. This is used to make the screen more readable in bright + * daylight for a short duration. + * <p> + * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. + * </p> + * + * @param time The time when the request to boost was issued, in the + * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly + * order the boost request with other power management functions. It should be set + * to the timestamp of the input event that caused the request to boost. + * + * @hide Requires signature permission. + */ + public void boostScreenBrightness(long time) { + try { + mService.boostScreenBrightness(time); + } catch (RemoteException e) { + } + } + + /** * Sets the brightness of the backlights (screen, keyboard, button). * <p> * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission. diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index 14f4a83..6b6f540 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -25,6 +25,58 @@ import android.view.Display; */ public abstract class PowerManagerInternal { /** + * Wakefulness: The device is asleep. It can only be awoken by a call to wakeUp(). + * The screen should be off or in the process of being turned off by the display controller. + * The device typically passes through the dozing state first. + */ + public static final int WAKEFULNESS_ASLEEP = 0; + + /** + * Wakefulness: The device is fully awake. It can be put to sleep by a call to goToSleep(). + * When the user activity timeout expires, the device may start dreaming or go to sleep. + */ + public static final int WAKEFULNESS_AWAKE = 1; + + /** + * Wakefulness: The device is dreaming. It can be awoken by a call to wakeUp(), + * which ends the dream. The device goes to sleep when goToSleep() is called, when + * the dream ends or when unplugged. + * User activity may brighten the screen but does not end the dream. + */ + public static final int WAKEFULNESS_DREAMING = 2; + + /** + * Wakefulness: The device is dozing. It is almost asleep but is allowing a special + * low-power "doze" dream to run which keeps the display on but lets the application + * processor be suspended. It can be awoken by a call to wakeUp() which ends the dream. + * The device fully goes to sleep if the dream cannot be started or ends on its own. + */ + public static final int WAKEFULNESS_DOZING = 3; + + public static String wakefulnessToString(int wakefulness) { + switch (wakefulness) { + case WAKEFULNESS_ASLEEP: + return "Asleep"; + case WAKEFULNESS_AWAKE: + return "Awake"; + case WAKEFULNESS_DREAMING: + return "Dreaming"; + case WAKEFULNESS_DOZING: + return "Dozing"; + default: + return Integer.toString(wakefulness); + } + } + + /** + * Returns true if the wakefulness state represents an interactive state + * as defined by {@link android.os.PowerManager#isInteractive}. + */ + public static boolean isInteractive(int wakefulness) { + return wakefulness == WAKEFULNESS_AWAKE || wakefulness == WAKEFULNESS_DREAMING; + } + + /** * Used by the window manager to override the screen brightness based on the * current foreground activity. * diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index c8d0fd5..3e80ed0 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -24,17 +24,13 @@ import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.database.Cursor; -import android.location.Country; -import android.location.CountryDetector; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.provider.ContactsContract.Data; import android.provider.ContactsContract.DataUsageFeedback; import android.telecom.PhoneAccountHandle; -import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.CallerInfo; @@ -387,10 +383,12 @@ public class CallLog { public static Uri addCall(CallerInfo ci, Context context, String number, int presentation, int callType, int features, PhoneAccountHandle accountHandle, long start, int duration, Long dataUsage) { + // FIXME using -1 as subId instead of SubscriptionManager.INVALID_SUB_ID return addCall(ci, context, number, presentation, callType, features, accountHandle, start, duration, dataUsage, false); } + /** * Adds a call to the call log. * @@ -406,6 +404,7 @@ public class CallLog { * @param accountHandle The accountHandle object identifying the provider of the call * @param start time stamp for the call in milliseconds * @param duration call duration in seconds + * @param subId the subscription id. * @param dataUsage data usage for the call in bytes, null if data usage was not tracked for * the call. * @param addForAllUsers If true, the call is added to the call log of all currently @@ -463,6 +462,7 @@ public class CallLog { values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString); values.put(PHONE_ACCOUNT_ID, accountId); values.put(NEW, Integer.valueOf(1)); + if (callType == MISSED_TYPE) { values.put(IS_READ, Integer.valueOf(0)); } @@ -503,13 +503,12 @@ public class CallLog { if (cursor != null) { try { if (cursor.getCount() > 0 && cursor.moveToFirst()) { - final String dataId = cursor.getString(0); - updateDataUsageStatForData(resolver, dataId); - if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS - && callType == Calls.OUTGOING_TYPE - && TextUtils.isEmpty(ci.normalizedNumber)) { - updateNormalizedNumber(context, resolver, dataId, number); - } + final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() + .appendPath(cursor.getString(0)) + .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, + DataUsageFeedback.USAGE_TYPE_CALL) + .build(); + resolver.update(feedbackUri, new ContentValues(), null, null); } } finally { cursor.close(); @@ -582,53 +581,5 @@ public class CallLog { + " LIMIT -1 OFFSET 500)", null); return result; } - - private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { - final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() - .appendPath(dataId) - .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, - DataUsageFeedback.USAGE_TYPE_CALL) - .build(); - resolver.update(feedbackUri, new ContentValues(), null, null); - } - - /** - * Update the normalized phone number for the given dataId in the ContactsProvider, based - * on the user's current country. - */ - private static void updateNormalizedNumber(Context context, ContentResolver resolver, - String dataId, String number) { - if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { - return; - } - - final String countryIso = getCurrentCountryIso(context); - if (TextUtils.isEmpty(countryIso)) { - return; - } - - final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, - getCurrentCountryIso(context)); - if (TextUtils.isEmpty(normalizedNumber)) { - return; - } - - final ContentValues values = new ContentValues(); - values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); - resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); - } - - private static String getCurrentCountryIso(Context context) { - String countryIso = null; - final CountryDetector detector = (CountryDetector) context.getSystemService( - Context.COUNTRY_DETECTOR); - if (detector != null) { - final Country country = detector.detectCountry(); - if (country != null) { - countryIso = country.getCountryIso(); - } - } - return countryIso; - } } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 73c7cc3..fbfd53e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5086,6 +5086,12 @@ public final class Settings { public static final String AIRPLANE_MODE_ON = "airplane_mode_on"; /** + * Whether Theater Mode is on. + * {@hide} + */ + public static final String THEATER_MODE_ON = "theater_mode_on"; + + /** * Constant for use in AIRPLANE_MODE_RADIOS to specify Bluetooth radio. */ public static final String RADIO_BLUETOOTH = "bluetooth"; diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 26e9a30..076baf5 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -23,6 +23,7 @@ import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.ViewRootImpl; import android.view.WindowInsets; + import com.android.internal.R; import com.android.internal.os.HandlerCaller; import com.android.internal.view.BaseIWindow; @@ -32,18 +33,17 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.app.WallpaperManager; -import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; +import android.hardware.display.DisplayManager; +import android.hardware.display.DisplayManager.DisplayListener; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.PowerManager; import android.os.RemoteException; import android.util.Log; import android.view.Display; @@ -139,7 +139,6 @@ public abstract class WallpaperService extends Service { boolean mInitializing = true; boolean mVisible; - boolean mScreenOn = true; boolean mReportedVisible; boolean mDestroyed; @@ -191,20 +190,10 @@ public abstract class WallpaperService extends Service { float mPendingYOffsetStep; boolean mPendingSync; MotionEvent mPendingMove; - - final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) { - mScreenOn = true; - reportVisibility(); - } else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { - mScreenOn = false; - reportVisibility(); - } - } - }; - + + DisplayManager mDisplayManager; + Display mDisplay; + final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() { { mRequestedFormat = PixelFormat.RGBX_8888; @@ -536,8 +525,8 @@ public abstract class WallpaperService extends Service { out.print(prefix); out.print("mInitializing="); out.print(mInitializing); out.print(" mDestroyed="); out.println(mDestroyed); out.print(prefix); out.print("mVisible="); out.print(mVisible); - out.print(" mScreenOn="); out.print(mScreenOn); out.print(" mReportedVisible="); out.println(mReportedVisible); + out.print(prefix); out.print("mDisplay="); out.println(mDisplay); out.print(prefix); out.print("mCreated="); out.print(mCreated); out.print(" mSurfaceCreated="); out.print(mSurfaceCreated); out.print(" mIsCreating="); out.print(mIsCreating); @@ -701,8 +690,8 @@ public abstract class WallpaperService extends Service { if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface + ", frame=" + mWinFrame); - int w = mWinFrame.width(); - int h = mWinFrame.height(); + int w = mWinFrame.width() + mOverscanInsets.left + mOverscanInsets.right; + int h = mWinFrame.height() + mOverscanInsets.top + mOverscanInsets.bottom; if (!fixedSize) { final Rect padding = mIWallpaperEngine.mDisplayPadding; @@ -875,13 +864,10 @@ public abstract class WallpaperService extends Service { mWindow.setSession(mSession); - mScreenOn = ((PowerManager)getSystemService(Context.POWER_SERVICE)).isScreenOn(); + mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE); + mDisplayManager.registerDisplayListener(mDisplayListener, mCaller.getHandler()); + mDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_SCREEN_ON); - filter.addAction(Intent.ACTION_SCREEN_OFF); - registerReceiver(mReceiver, filter); - if (DEBUG) Log.v(TAG, "onCreate(): " + this); onCreate(mSurfaceHolder); @@ -920,7 +906,8 @@ public abstract class WallpaperService extends Service { void reportVisibility() { if (!mDestroyed) { - boolean visible = mVisible && mScreenOn; + boolean visible = mVisible + & mDisplay != null && mDisplay.getState() != Display.STATE_OFF; if (mReportedVisible != visible) { mReportedVisible = visible; if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + visible @@ -1023,7 +1010,11 @@ public abstract class WallpaperService extends Service { } mDestroyed = true; - + + if (mDisplayManager != null) { + mDisplayManager.unregisterDisplayListener(mDisplayListener); + } + if (mVisible) { mVisible = false; if (DEBUG) Log.v(TAG, "onVisibilityChanged(false): " + this); @@ -1034,9 +1025,7 @@ public abstract class WallpaperService extends Service { if (DEBUG) Log.v(TAG, "onDestroy(): " + this); onDestroy(); - - unregisterReceiver(mReceiver); - + if (mCreated) { try { if (DEBUG) Log.v(TAG, "Removing window and destroying surface " @@ -1061,8 +1050,25 @@ public abstract class WallpaperService extends Service { } } } + + private final DisplayListener mDisplayListener = new DisplayListener() { + @Override + public void onDisplayChanged(int displayId) { + if (mDisplay.getDisplayId() == displayId) { + reportVisibility(); + } + } + + @Override + public void onDisplayRemoved(int displayId) { + } + + @Override + public void onDisplayAdded(int displayId) { + } + }; } - + class IWallpaperEngineWrapper extends IWallpaperEngine.Stub implements HandlerCaller.Callback { private final HandlerCaller mCaller; diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 3770b8a..828e082 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -53,6 +53,9 @@ public class Surface implements Parcelable { private static native void nativeAllocateBuffers(long nativeObject); + private static native int nativeGetWidth(long nativeObject); + private static native int nativeGetHeight(long nativeObject); + public static final Parcelable.Creator<Surface> CREATOR = new Parcelable.Creator<Surface>() { @Override @@ -87,6 +90,8 @@ public class Surface implements Parcelable { // non compatibility mode. private Matrix mCompatibleMatrix; + private HwuiContext mHwuiContext; + /** @hide */ @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270}) @Retention(RetentionPolicy.SOURCE) @@ -171,6 +176,10 @@ public class Surface implements Parcelable { nativeRelease(mNativeObject); setNativeObjectLocked(0); } + if (mHwuiContext != null) { + mHwuiContext.destroy(); + mHwuiContext = null; + } } } @@ -264,27 +273,63 @@ public class Surface implements Parcelable { * @param canvas The canvas previously obtained from {@link #lockCanvas}. */ public void unlockCanvasAndPost(Canvas canvas) { + synchronized (mLock) { + checkNotReleasedLocked(); + + if (mHwuiContext != null) { + mHwuiContext.unlockAndPost(canvas); + } else { + unlockSwCanvasAndPost(canvas); + } + } + } + + private void unlockSwCanvasAndPost(Canvas canvas) { if (canvas != mCanvas) { throw new IllegalArgumentException("canvas object must be the same instance that " + "was previously returned by lockCanvas"); } + if (mNativeObject != mLockedObject) { + Log.w(TAG, "WARNING: Surface's mNativeObject (0x" + + Long.toHexString(mNativeObject) + ") != mLockedObject (0x" + + Long.toHexString(mLockedObject) +")"); + } + if (mLockedObject == 0) { + throw new IllegalStateException("Surface was not locked"); + } + try { + nativeUnlockCanvasAndPost(mLockedObject, canvas); + } finally { + nativeRelease(mLockedObject); + mLockedObject = 0; + } + } + /** + * Gets a {@link Canvas} for drawing into this surface. + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated + * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported"> + * unsupported drawing operations</a> for a list of what is and isn't + * supported in a hardware-accelerated canvas. + * + * @return A canvas for drawing into the surface. + * + * @throws IllegalStateException If the canvas cannot be locked. + * @hide + */ + public Canvas lockHardwareCanvas() { synchronized (mLock) { checkNotReleasedLocked(); - if (mNativeObject != mLockedObject) { - Log.w(TAG, "WARNING: Surface's mNativeObject (0x" + - Long.toHexString(mNativeObject) + ") != mLockedObject (0x" + - Long.toHexString(mLockedObject) +")"); - } - if (mLockedObject == 0) { - throw new IllegalStateException("Surface was not locked"); - } - try { - nativeUnlockCanvasAndPost(mLockedObject, canvas); - } finally { - nativeRelease(mLockedObject); - mLockedObject = 0; + if (mHwuiContext == null) { + mHwuiContext = new HwuiContext(); } + return mHwuiContext.lockCanvas( + nativeGetWidth(mNativeObject), + nativeGetHeight(mNativeObject)); } } @@ -415,6 +460,9 @@ public class Surface implements Parcelable { } mNativeObject = ptr; mGenerationId += 1; + if (mHwuiContext != null) { + mHwuiContext.updateSurface(); + } } } @@ -518,4 +566,50 @@ public class Surface implements Parcelable { mOrigMatrix.set(m); } } + + private final class HwuiContext { + private final RenderNode mRenderNode; + private long mHwuiRenderer; + private HardwareCanvas mCanvas; + + HwuiContext() { + mRenderNode = RenderNode.create("HwuiCanvas", null); + mRenderNode.setClipToBounds(false); + mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject); + } + + Canvas lockCanvas(int width, int height) { + if (mCanvas != null) { + throw new IllegalStateException("Surface was already locked!"); + } + mCanvas = mRenderNode.start(width, height); + return mCanvas; + } + + void unlockAndPost(Canvas canvas) { + if (canvas != mCanvas) { + throw new IllegalArgumentException("canvas object must be the same instance that " + + "was previously returned by lockCanvas"); + } + mRenderNode.end(mCanvas); + mCanvas = null; + nHwuiDraw(mHwuiRenderer); + } + + void updateSurface() { + nHwuiSetSurface(mHwuiRenderer, mNativeObject); + } + + void destroy() { + if (mHwuiRenderer != 0) { + nHwuiDestroy(mHwuiRenderer); + mHwuiRenderer = 0; + } + } + } + + private static native long nHwuiCreate(long rootNode, long surface); + private static native void nHwuiSetSurface(long renderer, long surface); + private static native void nHwuiDraw(long renderer); + private static native void nHwuiDestroy(long renderer); } diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index a9444b4..0d4454d 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -37,6 +37,8 @@ public final class ViewTreeObserver { private CopyOnWriteArrayList<OnWindowAttachListener> mOnWindowAttachListeners; private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; + private CopyOnWriteArrayList<OnEnterAnimationCompleteListener> + mOnEnterAnimationCompleteListeners; // Non-recursive listeners use CopyOnWriteArray // Any listener invoked from ViewRootImpl.performTraversals() should not be recursive @@ -298,6 +300,13 @@ public final class ViewTreeObserver { } /** + * @hide + */ + public interface OnEnterAnimationCompleteListener { + public void onEnterAnimationComplete(); + } + + /** * Creates a new ViewTreeObserver. This constructor should not be called */ ViewTreeObserver() { @@ -715,6 +724,29 @@ public final class ViewTreeObserver { mOnComputeInternalInsetsListeners.remove(victim); } + /** + * @hide + */ + public void addOnEnterAnimationCompleteListener(OnEnterAnimationCompleteListener listener) { + checkIsAlive(); + if (mOnEnterAnimationCompleteListeners == null) { + mOnEnterAnimationCompleteListeners = + new CopyOnWriteArrayList<OnEnterAnimationCompleteListener>(); + } + mOnEnterAnimationCompleteListeners.add(listener); + } + + /** + * @hide + */ + public void removeOnEnterAnimationCompleteListener(OnEnterAnimationCompleteListener listener) { + checkIsAlive(); + if (mOnEnterAnimationCompleteListeners == null) { + return; + } + mOnEnterAnimationCompleteListeners.remove(listener); + } + private void checkIsAlive() { if (!mAlive) { throw new IllegalStateException("This ViewTreeObserver is not alive, call " @@ -936,6 +968,23 @@ public final class ViewTreeObserver { } /** + * @hide + */ + public final void dispatchOnEnterAnimationComplete() { + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnEnterAnimationCompleteListener> listeners = + mOnEnterAnimationCompleteListeners; + if (listeners != null && !listeners.isEmpty()) { + for (OnEnterAnimationCompleteListener listener : listeners) { + listener.onEnterAnimationComplete(); + } + } + } + + /** * Copy on write array. This array is not thread safe, and only one loop can * iterate over this array at any given time. This class avoids allocations * until a concurrent modification happens. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 47ee52e..7b22c88 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1116,6 +1116,13 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400; /** + * Flag that prevents the wallpaper behind the current window from receiving touch events. + * + * {@hide} + */ + public static final int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS = 0x00000800; + + /** * Control flags that are private to the platform. * @hide */ |
