diff options
Diffstat (limited to 'services')
35 files changed, 1200 insertions, 664 deletions
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 0a6f23c..6ae16a4 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -93,6 +93,7 @@ public class BatteryService extends Binder { private boolean mAcOnline; private boolean mUsbOnline; + private boolean mWirelessOnline; private int mBatteryStatus; private int mBatteryHealth; private boolean mBatteryPresent; @@ -150,7 +151,8 @@ public class BatteryService extends Binder { public final boolean isPowered() { // assume we are powered if battery state is unknown so the "stay on while plugged in" option will work. - return (mAcOnline || mUsbOnline || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN); + return (mAcOnline || mUsbOnline || mWirelessOnline + || mBatteryStatus == BatteryManager.BATTERY_STATUS_UNKNOWN); } public final boolean isPowered(int plugTypeSet) { @@ -169,6 +171,9 @@ public class BatteryService extends Binder { if (mUsbOnline) { plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB; } + if (mWirelessOnline) { + plugTypeBit |= BatteryManager.BATTERY_PLUGGED_WIRELESS; + } return (plugTypeSet & plugTypeBit) != 0; } @@ -243,6 +248,8 @@ public class BatteryService extends Binder { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; + } else if (mWirelessOnline) { + mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; } else { mPlugType = BATTERY_PLUGGED_NONE; } @@ -398,6 +405,7 @@ public class BatteryService extends Binder { " temperature: " + mBatteryTemperature + " technology: " + mBatteryTechnology + " AC powered:" + mAcOnline + " USB powered:" + mUsbOnline + + " Wireless powered:" + mWirelessOnline + " icon:" + icon + " invalid charger:" + mInvalidCharger); } @@ -503,6 +511,7 @@ public class BatteryService extends Binder { pw.println("Current Battery Service state:"); pw.println(" AC powered: " + mAcOnline); pw.println(" USB powered: " + mUsbOnline); + pw.println(" Wireless powered: " + mWirelessOnline); pw.println(" status: " + mBatteryStatus); pw.println(" health: " + mBatteryHealth); pw.println(" present: " + mBatteryPresent); @@ -523,6 +532,8 @@ public class BatteryService extends Binder { mAcOnline = Integer.parseInt(value) != 0; } else if ("usb".equals(key)) { mUsbOnline = Integer.parseInt(value) != 0; + } else if ("wireless".equals(key)) { + mWirelessOnline = Integer.parseInt(value) != 0; } else if ("status".equals(key)) { mBatteryStatus = Integer.parseInt(value); } else if ("level".equals(key)) { @@ -603,4 +614,3 @@ public class BatteryService extends Binder { } } } - diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 375ba68..cb6ce4b 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -2592,6 +2592,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { // @see bug/4455071 handleConnectivityChange(info.getType(), false); break; + case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: + info = (NetworkInfo) msg.obj; + type = info.getType(); + updateNetworkSettings(mNetTrackers[type]); + break; } } } diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java index 8bdd7be..ef09b01 100644 --- a/services/java/com/android/server/DockObserver.java +++ b/services/java/com/android/server/DockObserver.java @@ -18,10 +18,6 @@ package com.android.server; import static android.provider.Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK; -import com.android.server.power.PowerManagerService; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -30,6 +26,7 @@ import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; @@ -47,7 +44,7 @@ import java.io.FileReader; /** * <p>DockObserver monitors for a docking station. */ -class DockObserver extends UEventObserver { +final class DockObserver extends UEventObserver { private static final String TAG = DockObserver.class.getSimpleName(); private static final boolean LOG = false; @@ -56,7 +53,9 @@ class DockObserver extends UEventObserver { private static final int DEFAULT_DOCK = 1; - private static final int MSG_DOCK_STATE = 0; + private static final int MSG_DOCK_STATE_CHANGED = 0; + + private final Object mLock = new Object(); private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; @@ -78,7 +77,7 @@ class DockObserver extends UEventObserver { Slog.v(TAG, "Dock UEVENT: " + event.toString()); } - synchronized (this) { + synchronized (mLock) { try { int newState = Integer.parseInt(event.get("SWITCH_STATE")); if (newState != mDockState) { @@ -96,7 +95,7 @@ class DockObserver extends UEventObserver { (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); pm.wakeUp(SystemClock.uptimeMillis()); } - update(); + updateLocked(); } } } catch (NumberFormatException e) { @@ -105,132 +104,142 @@ class DockObserver extends UEventObserver { } } - private final void init() { - char[] buffer = new char[1024]; - - try { - FileReader file = new FileReader(DOCK_STATE_PATH); - int len = file.read(buffer, 0, 1024); - file.close(); - mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim()); - } catch (FileNotFoundException e) { - Slog.w(TAG, "This kernel does not have dock station support"); - } catch (Exception e) { - Slog.e(TAG, "" , e); + private void init() { + synchronized (mLock) { + try { + char[] buffer = new char[1024]; + FileReader file = new FileReader(DOCK_STATE_PATH); + try { + int len = file.read(buffer, 0, 1024); + mDockState = Integer.valueOf((new String(buffer, 0, len)).trim()); + mPreviousDockState = mDockState; + } finally { + file.close(); + } + } catch (FileNotFoundException e) { + Slog.w(TAG, "This kernel does not have dock station support"); + } catch (Exception e) { + Slog.e(TAG, "" , e); + } } } void systemReady() { - synchronized (this) { + synchronized (mLock) { // don't bother broadcasting undocked here if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) { - update(); + updateLocked(); } mSystemReady = true; } } - private final void update() { - mHandler.sendEmptyMessage(MSG_DOCK_STATE); + private void updateLocked() { + mHandler.sendEmptyMessage(MSG_DOCK_STATE_CHANGED); } - private static boolean isScreenSaverActivatedOnDock(Context context) { - return 0 != Settings.Secure.getInt( - context.getContentResolver(), SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK); - } + private void handleDockStateChange() { + synchronized (mLock) { + Slog.i(TAG, "Dock state changed: " + mDockState); - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_DOCK_STATE: - synchronized (this) { - Slog.i(TAG, "Dock state changed: " + mDockState); + final ContentResolver cr = mContext.getContentResolver(); - final ContentResolver cr = mContext.getContentResolver(); + if (Settings.Secure.getInt(cr, + Settings.Secure.DEVICE_PROVISIONED, 0) == 0) { + Slog.i(TAG, "Device not provisioned, skipping dock broadcast"); + return; + } - if (Settings.Secure.getInt(cr, - Settings.Secure.DEVICE_PROVISIONED, 0) == 0) { - Slog.i(TAG, "Device not provisioned, skipping dock broadcast"); - return; - } - // Pack up the values and broadcast them to everyone - Intent intent = new Intent(Intent.ACTION_DOCK_EVENT); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); - intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState); - - // Check if this is Bluetooth Dock - // TODO(BT): Get Dock address. - String address = null; - if (address != null) - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address)); - - // User feedback to confirm dock connection. Particularly - // useful for flaky contact pins... - if (Settings.System.getInt(cr, - Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1) - { - String whichSound = null; - if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) { - if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) || - (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || - (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) { - whichSound = Settings.System.DESK_UNDOCK_SOUND; - } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) { - whichSound = Settings.System.CAR_UNDOCK_SOUND; - } - } else { - if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) || - (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || - (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) { - whichSound = Settings.System.DESK_DOCK_SOUND; - } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) { - whichSound = Settings.System.CAR_DOCK_SOUND; - } - } + // Pack up the values and broadcast them to everyone + Intent intent = new Intent(Intent.ACTION_DOCK_EVENT); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState); + + // Check if this is Bluetooth Dock + // TODO(BT): Get Dock address. + // String address = null; + // if (address != null) { + // intent.putExtra(BluetoothDevice.EXTRA_DEVICE, + // BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address)); + // } + + // User feedback to confirm dock connection. Particularly + // useful for flaky contact pins... + if (Settings.System.getInt(cr, + Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1) { + String whichSound = null; + if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) { + if ((mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) || + (mPreviousDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || + (mPreviousDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) { + whichSound = Settings.System.DESK_UNDOCK_SOUND; + } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) { + whichSound = Settings.System.CAR_UNDOCK_SOUND; + } + } else { + if ((mDockState == Intent.EXTRA_DOCK_STATE_DESK) || + (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || + (mDockState == Intent.EXTRA_DOCK_STATE_HE_DESK)) { + whichSound = Settings.System.DESK_DOCK_SOUND; + } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) { + whichSound = Settings.System.CAR_DOCK_SOUND; + } + } - if (whichSound != null) { - final String soundPath = Settings.System.getString(cr, whichSound); - if (soundPath != null) { - final Uri soundUri = Uri.parse("file://" + soundPath); - if (soundUri != null) { - final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); - if (sfx != null) { - sfx.setStreamType(AudioManager.STREAM_SYSTEM); - sfx.play(); - } - } - } + if (whichSound != null) { + final String soundPath = Settings.System.getString(cr, whichSound); + if (soundPath != null) { + final Uri soundUri = Uri.parse("file://" + soundPath); + if (soundUri != null) { + final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); + if (sfx != null) { + sfx.setStreamType(AudioManager.STREAM_SYSTEM); + sfx.play(); } } + } + } + } - IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); - if (mgr != null) { - // dreams feature enabled - boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED; - if (undocked) { - try { - if (mgr.isDreaming()) { - mgr.awaken(); - } - } catch (RemoteException e) { - Slog.w(TAG, "Unable to awaken!", e); - } - } else { - if (isScreenSaverActivatedOnDock(mContext)) { - try { - mgr.dream(); - } catch (RemoteException e) { - Slog.w(TAG, "Unable to dream!", e); - } - } - } - } else { - // dreams feature not enabled, send legacy intent - mContext.sendStickyBroadcast(intent); + IDreamManager mgr = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); + if (mgr != null) { + // dreams feature enabled + boolean undocked = mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED; + if (undocked) { + try { + if (mgr.isDreaming()) { + mgr.awaken(); } + } catch (RemoteException e) { + Slog.w(TAG, "Unable to awaken!", e); } + } else { + if (isScreenSaverActivatedOnDock(mContext)) { + try { + mgr.dream(); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to dream!", e); + } + } + } + } else { + // dreams feature not enabled, send legacy intent + mContext.sendStickyBroadcast(intent); + } + } + } + + private static boolean isScreenSaverActivatedOnDock(Context context) { + return Settings.Secure.getInt(context.getContentResolver(), + SCREENSAVER_ACTIVATE_ON_DOCK, DEFAULT_DOCK) != 0; + } + + private final Handler mHandler = new Handler(Looper.myLooper(), null, true) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_DOCK_STATE_CHANGED: + handleDockStateChange(); break; } } diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index bb005d9..8a564f7 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -63,6 +63,7 @@ import com.android.internal.location.ProviderRequest; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GpsLocationProvider; +import com.android.server.location.LocationBlacklist; import com.android.server.location.LocationFudger; import com.android.server.location.LocationProviderInterface; import com.android.server.location.LocationProviderProxy; @@ -132,8 +133,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs private IGpsStatusProvider mGpsStatusProvider; private INetInitiatedListener mNetInitiatedListener; private LocationWorkerHandler mLocationHandler; - // track the passive provider for some special cases - private PassiveProvider mPassiveProvider; + private PassiveProvider mPassiveProvider; // track passive provider for special cases + private LocationBlacklist mBlacklist; // --- fields below are protected by mWakeLock --- private int mPendingBroadcasts; @@ -208,7 +209,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs synchronized (mLock) { loadProvidersLocked(); } - mGeofenceManager = new GeofenceManager(mContext); + mBlacklist = new LocationBlacklist(mContext, mLocationHandler); + mBlacklist.init(); + mGeofenceManager = new GeofenceManager(mContext, mBlacklist); mLocationFudger = new LocationFudger(); // Register for Network (Wifi or Mobile) updates @@ -965,7 +968,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs final int uid = Binder.getCallingUid(); Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName); - // so wakelock calls will succeed (not totally sure this is still needed) + // providers may use public location API's, need to clear identity long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1015,7 +1018,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs final int uid = Binder.getCallingUid(); Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName); - // so wakelock calls will succeed (not totally sure this is still needed) + // providers may use public location API's, need to clear identity long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1063,10 +1066,17 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs } @Override - public Location getLastLocation(LocationRequest request) { + public Location getLastLocation(LocationRequest request, String packageName) { if (D) Log.d(TAG, "getLastLocation: " + request); if (request == null) request = DEFAULT_LOCATION_REQUEST; String perm = checkPermissionAndRequest(request); + checkPackageName(packageName); + + if (mBlacklist.isBlacklisted(packageName)) { + if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + + packageName); + return null; + } synchronized (mLock) { // Figure out the provider. Either its explicitly request (deprecated API's), @@ -1097,7 +1107,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs if (D) Log.d(TAG, "requestGeofence: " + request + " " + geofence + " " + intent); - mGeofenceManager.addFence(request, geofence, intent, Binder.getCallingUid(), packageName); + // geo-fence manager uses the public location API, need to clear identity + int uid = Binder.getCallingUid(); + long identity = Binder.clearCallingIdentity(); + try { + mGeofenceManager.addFence(request, geofence, intent, uid, packageName); + } finally { + Binder.restoreCallingIdentity(identity); + } } @Override @@ -1108,7 +1125,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); - mGeofenceManager.removeFence(geofence, intent); + // geo-fence manager uses the public location API, need to clear identity + long identity = Binder.clearCallingIdentity(); + try { + mGeofenceManager.removeFence(geofence, intent); + } finally { + Binder.restoreCallingIdentity(identity); + } } @@ -1325,6 +1348,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs for (UpdateRecord r : records) { Receiver receiver = r.mReceiver; boolean receiverDead = false; + + if (mBlacklist.isBlacklisted(receiver.mPackageName)) { + if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + + receiver.mPackageName); + continue; + } + if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) { location = lastLocation; // use fine location } else { @@ -1716,8 +1746,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Obs for (String i : mDisabledProviders) { pw.println(" " + i); } - } + pw.append(" "); + mBlacklist.dump(pw); if (mMockProviders.size() > 0) { pw.println(" Mock Providers:"); for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index c471dd2..a117b06 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -155,13 +155,12 @@ class ServerThread extends Thread { power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); - Slog.i(TAG, "Display Manager"); - display = new DisplayManagerService(); - ServiceManager.addService(Context.DISPLAY_SERVICE, display, true); - Slog.i(TAG, "Activity Manager"); context = ActivityManagerService.main(factoryTest); - display.setContext(context); + + Slog.i(TAG, "Display Manager"); + display = new DisplayManagerService(context); + ServiceManager.addService(Context.DISPLAY_SERVICE, display, true); Slog.i(TAG, "Telephony Registry"); ServiceManager.addService("telephony.registry", new TelephonyRegistry(context)); diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 1d248b2..afd7d0e 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -768,10 +768,6 @@ class WallpaperManagerService extends IWallpaperManager.Stub { WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper); intent.setComponent(componentName); int serviceUserId = wallpaper.userId; - // Because the image wallpaper is running in the system ui - if (componentName.equals(wallpaper.imageWallpaperComponent)) { - serviceUserId = 0; - } intent.putExtra(Intent.EXTRA_CLIENT_LABEL, com.android.internal.R.string.wallpaper_binding_label); intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java index 96ac493..56c0fdf 100644 --- a/services/java/com/android/server/WiredAccessoryObserver.java +++ b/services/java/com/android/server/WiredAccessoryObserver.java @@ -16,12 +16,12 @@ package com.android.server; -import android.app.ActivityManagerNative; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.WakeLock; @@ -39,7 +39,7 @@ import java.util.List; /** * <p>WiredAccessoryObserver monitors for a wired headset on the main board or dock. */ -class WiredAccessoryObserver extends UEventObserver { +final class WiredAccessoryObserver extends UEventObserver { private static final String TAG = WiredAccessoryObserver.class.getSimpleName(); private static final boolean LOG = true; private static final int BIT_HEADSET = (1 << 0); @@ -50,122 +50,32 @@ class WiredAccessoryObserver extends UEventObserver { private static final int SUPPORTED_HEADSETS = (BIT_HEADSET|BIT_HEADSET_NO_MIC| BIT_USB_HEADSET_ANLG|BIT_USB_HEADSET_DGTL| BIT_HDMI_AUDIO); - private static final int HEADSETS_WITH_MIC = BIT_HEADSET; - private static class UEventInfo { - private final String mDevName; - private final int mState1Bits; - private final int mState2Bits; - - public UEventInfo(String devName, int state1Bits, int state2Bits) { - mDevName = devName; - mState1Bits = state1Bits; - mState2Bits = state2Bits; - } - - public String getDevName() { return mDevName; } - - public String getDevPath() { - return String.format("/devices/virtual/switch/%s", mDevName); - } - - public String getSwitchStatePath() { - return String.format("/sys/class/switch/%s/state", mDevName); - } - - public boolean checkSwitchExists() { - File f = new File(getSwitchStatePath()); - return ((null != f) && f.exists()); - } - - public int computeNewHeadsetState(int headsetState, int switchState) { - int preserveMask = ~(mState1Bits | mState2Bits); - int setBits = ((switchState == 1) ? mState1Bits : - ((switchState == 2) ? mState2Bits : 0)); - - return ((headsetState & preserveMask) | setBits); - } - } - - private static List<UEventInfo> makeObservedUEventList() { - List<UEventInfo> retVal = new ArrayList<UEventInfo>(); - UEventInfo uei; - - // Monitor h2w - uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC); - if (uei.checkSwitchExists()) { - retVal.add(uei); - } else { - Slog.w(TAG, "This kernel does not have wired headset support"); - } - - // Monitor USB - uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL); - if (uei.checkSwitchExists()) { - retVal.add(uei); - } else { - Slog.w(TAG, "This kernel does not have usb audio support"); - } + private final Object mLock = new Object(); - // Monitor HDMI - // - // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled - // only when the HDMI driver has a video mode configured, and the downstream sink indicates - // support for audio in its EDID. - // - // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi" - // switch instead. - uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0); - if (uei.checkSwitchExists()) { - retVal.add(uei); - } else { - uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0); - if (uei.checkSwitchExists()) { - retVal.add(uei); - } else { - Slog.w(TAG, "This kernel does not have HDMI audio support"); - } - } - - return retVal; - } - - private static List<UEventInfo> uEventInfo = makeObservedUEventList(); + private final Context mContext; + private final WakeLock mWakeLock; // held while there is a pending route change + private final AudioManager mAudioManager; + private final List<UEventInfo> mUEventInfo; private int mHeadsetState; private int mPrevHeadsetState; private String mHeadsetName; - private final Context mContext; - private final WakeLock mWakeLock; // held while there is a pending route change - - private final AudioManager mAudioManager; - public WiredAccessoryObserver(Context context) { mContext = context; + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryObserver"); mWakeLock.setReferenceCounted(false); mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); + mUEventInfo = makeObservedUEventList(); + context.registerReceiver(new BootCompletedReceiver(), new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null); } - private final class BootCompletedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - // At any given time accessories could be inserted - // one on the board, one on the dock and one on HDMI: - // observe three UEVENTs - init(); // set initial status - for (int i = 0; i < uEventInfo.size(); ++i) { - UEventInfo uei = uEventInfo.get(i); - startObserving("DEVPATH="+uei.getDevPath()); - } - } - } - @Override public void onUEvent(UEventObserver.UEvent event) { if (LOG) Slog.v(TAG, "Headset UEVENT: " + event.toString()); @@ -174,56 +84,64 @@ class WiredAccessoryObserver extends UEventObserver { String devPath = event.get("DEVPATH"); String name = event.get("SWITCH_NAME"); int state = Integer.parseInt(event.get("SWITCH_STATE")); - updateState(devPath, name, state); + synchronized (mLock) { + updateStateLocked(devPath, name, state); + } } catch (NumberFormatException e) { Slog.e(TAG, "Could not parse switch state from event " + event); } } - private synchronized final void updateState(String devPath, String name, int state) - { - for (int i = 0; i < uEventInfo.size(); ++i) { - UEventInfo uei = uEventInfo.get(i); - if (devPath.equals(uei.getDevPath())) { - update(name, uei.computeNewHeadsetState(mHeadsetState, state)); - return; + private void bootCompleted() { + synchronized (mLock) { + char[] buffer = new char[1024]; + mPrevHeadsetState = mHeadsetState; + + if (LOG) Slog.v(TAG, "init()"); + + for (int i = 0; i < mUEventInfo.size(); ++i) { + UEventInfo uei = mUEventInfo.get(i); + try { + int curState; + FileReader file = new FileReader(uei.getSwitchStatePath()); + int len = file.read(buffer, 0, 1024); + file.close(); + curState = Integer.valueOf((new String(buffer, 0, len)).trim()); + + if (curState > 0) { + updateStateLocked(uei.getDevPath(), uei.getDevName(), curState); + } + } catch (FileNotFoundException e) { + Slog.w(TAG, uei.getSwitchStatePath() + + " not found while attempting to determine initial switch state"); + } catch (Exception e) { + Slog.e(TAG, "" , e); + } } } - } - - private synchronized final void init() { - char[] buffer = new char[1024]; - mPrevHeadsetState = mHeadsetState; - - if (LOG) Slog.v(TAG, "init()"); - for (int i = 0; i < uEventInfo.size(); ++i) { - UEventInfo uei = uEventInfo.get(i); - try { - int curState; - FileReader file = new FileReader(uei.getSwitchStatePath()); - int len = file.read(buffer, 0, 1024); - file.close(); - curState = Integer.valueOf((new String(buffer, 0, len)).trim()); - - if (curState > 0) { - updateState(uei.getDevPath(), uei.getDevName(), curState); - } + // At any given time accessories could be inserted + // one on the board, one on the dock and one on HDMI: + // observe three UEVENTs + for (int i = 0; i < mUEventInfo.size(); ++i) { + UEventInfo uei = mUEventInfo.get(i); + startObserving("DEVPATH="+uei.getDevPath()); + } + } - } catch (FileNotFoundException e) { - Slog.w(TAG, uei.getSwitchStatePath() + - " not found while attempting to determine initial switch state"); - } catch (Exception e) { - Slog.e(TAG, "" , e); + private void updateStateLocked(String devPath, String name, int state) { + for (int i = 0; i < mUEventInfo.size(); ++i) { + UEventInfo uei = mUEventInfo.get(i); + if (devPath.equals(uei.getDevPath())) { + updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state)); + return; } } } - private synchronized final void update(String newName, int newState) { + private void updateLocked(String newName, int newState) { // Retain only relevant bits int headsetState = newState & SUPPORTED_HEADSETS; - int newOrOld = headsetState | mHeadsetState; - int delay = 0; int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG; int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL; int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC); @@ -254,28 +172,26 @@ class WiredAccessoryObserver extends UEventObserver { mHeadsetState = headsetState; mWakeLock.acquire(); - mHandler.sendMessage(mHandler.obtainMessage(0, - mHeadsetState, - mPrevHeadsetState, - mHeadsetName)); + + Message msg = mHandler.obtainMessage(0, mHeadsetState, mPrevHeadsetState, mHeadsetName); + mHandler.sendMessage(msg); } - private synchronized final void setDevicesState(int headsetState, - int prevHeadsetState, - String headsetName) { - int allHeadsets = SUPPORTED_HEADSETS; - for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { - if ((curHeadset & allHeadsets) != 0) { - setDeviceState(curHeadset, headsetState, prevHeadsetState, headsetName); - allHeadsets &= ~curHeadset; + private void setDevicesState( + int headsetState, int prevHeadsetState, String headsetName) { + synchronized (mLock) { + int allHeadsets = SUPPORTED_HEADSETS; + for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) { + if ((curHeadset & allHeadsets) != 0) { + setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName); + allHeadsets &= ~curHeadset; + } } } } - private final void setDeviceState(int headset, - int headsetState, - int prevHeadsetState, - String headsetName) { + private void setDeviceStateLocked(int headset, + int headsetState, int prevHeadsetState, String headsetName) { if ((headsetState & headset) != (prevHeadsetState & headset)) { int device; int state; @@ -308,11 +224,96 @@ class WiredAccessoryObserver extends UEventObserver { } } - private final Handler mHandler = new Handler() { + private static List<UEventInfo> makeObservedUEventList() { + List<UEventInfo> retVal = new ArrayList<UEventInfo>(); + UEventInfo uei; + + // Monitor h2w + uei = new UEventInfo("h2w", BIT_HEADSET, BIT_HEADSET_NO_MIC); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + Slog.w(TAG, "This kernel does not have wired headset support"); + } + + // Monitor USB + uei = new UEventInfo("usb_audio", BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + Slog.w(TAG, "This kernel does not have usb audio support"); + } + + // Monitor HDMI + // + // If the kernel has support for the "hdmi_audio" switch, use that. It will be signalled + // only when the HDMI driver has a video mode configured, and the downstream sink indicates + // support for audio in its EDID. + // + // If the kernel does not have an "hdmi_audio" switch, just fall back on the older "hdmi" + // switch instead. + uei = new UEventInfo("hdmi_audio", BIT_HDMI_AUDIO, 0); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + uei = new UEventInfo("hdmi", BIT_HDMI_AUDIO, 0); + if (uei.checkSwitchExists()) { + retVal.add(uei); + } else { + Slog.w(TAG, "This kernel does not have HDMI audio support"); + } + } + + return retVal; + } + + private final Handler mHandler = new Handler(Looper.myLooper(), null, true) { @Override public void handleMessage(Message msg) { setDevicesState(msg.arg1, msg.arg2, (String)msg.obj); mWakeLock.release(); } }; + + private static final class UEventInfo { + private final String mDevName; + private final int mState1Bits; + private final int mState2Bits; + + public UEventInfo(String devName, int state1Bits, int state2Bits) { + mDevName = devName; + mState1Bits = state1Bits; + mState2Bits = state2Bits; + } + + public String getDevName() { return mDevName; } + + public String getDevPath() { + return String.format("/devices/virtual/switch/%s", mDevName); + } + + public String getSwitchStatePath() { + return String.format("/sys/class/switch/%s/state", mDevName); + } + + public boolean checkSwitchExists() { + File f = new File(getSwitchStatePath()); + return ((null != f) && f.exists()); + } + + public int computeNewHeadsetState(int headsetState, int switchState) { + int preserveMask = ~(mState1Bits | mState2Bits); + int setBits = ((switchState == 1) ? mState1Bits : + ((switchState == 2) ? mState2Bits : 0)); + + return ((headsetState & preserveMask) | setBits); + } + } + + private final class BootCompletedReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + bootCompleted(); + } + } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 5e85e1a..944fd6b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2539,7 +2539,6 @@ public final class ActivityManagerService extends ActivityManagerNative // This is so super not safe, that only the system (or okay root) // can do it. - int userId = Binder.getOrigCallingUser(); final int callingUid = Binder.getCallingUid(); if (callingUid != 0 && callingUid != Process.myUid()) { throw new SecurityException( @@ -2548,7 +2547,7 @@ public final class ActivityManagerService extends ActivityManagerNative int ret = mMainStack.startActivityMayWait(null, uid, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, - null, null, null, null, options, userId); + null, null, null, null, options, UserHandle.getUserId(uid)); return ret; } diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java index ab2e428..15fbb98 100644 --- a/services/java/com/android/server/am/ProviderMap.java +++ b/services/java/com/android/server/am/ProviderMap.java @@ -127,7 +127,12 @@ public class ProviderMap { Slog.i(TAG, "Removing from providersByName name=" + name + " user=" + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId)); - getProvidersByName(optionalUserId).remove(name); + HashMap<String, ContentProviderRecord> map = getProvidersByName(optionalUserId); + // map returned by getProvidersByName wouldn't be null + map.remove(name); + if (map.size() == 0) { + mProvidersByNamePerUser.remove(optionalUserId); + } } } @@ -141,7 +146,12 @@ public class ProviderMap { Slog.i(TAG, "Removing from providersByClass name=" + name + " user=" + (optionalUserId == -1 ? Binder.getOrigCallingUser() : optionalUserId)); - getProvidersByClass(optionalUserId).remove(name); + HashMap<ComponentName, ContentProviderRecord> map = getProvidersByClass(optionalUserId); + // map returned by getProvidersByClass wouldn't be null + map.remove(name); + if (map.size() == 0) { + mProvidersByClassPerUser.remove(optionalUserId); + } } } diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java index b623906..f9fa7a8 100644 --- a/services/java/com/android/server/display/DisplayAdapter.java +++ b/services/java/com/android/server/display/DisplayAdapter.java @@ -16,38 +16,33 @@ package com.android.server.display; -import android.view.Display; - /** - * A display adapter makes a single display devices available to the system. + * A display adapter makes zero or more display devices available to the system + * and provides facilities for discovering when displays are connected or disconnected. * <p> * For now, all display adapters are registered in the system server but * in principle it could be done from other processes. * </p> */ public abstract class DisplayAdapter { - /** The current logical Display assignment for this adapter. Will change if other logical - * display is assigned to this adapter */ - private int mDisplayId = Display.NO_DISPLAY; - - /** Assign the displayId - * @hide */ - public void setDisplayId(int displayId) { - mDisplayId = displayId; - } - - /** Retrieve the displayId - * @hide */ - public int getDisplayId() { - return mDisplayId; - } - /** - * Gets the display adapter name. + * Gets the display adapter name for debugging purposes. + * * @return The display adapter name. */ public abstract String getName(); - // TODO: dynamically register display devices - public abstract DisplayDevice getDisplayDevice(); + /** + * Registers the display adapter with the display manager. + * The display adapter should register any built-in display devices now. + * Other display devices can be registered dynamically later. + * + * @param listener The listener for callbacks. + */ + public abstract void register(Listener listener); + + public interface Listener { + public void onDisplayDeviceAdded(DisplayDevice device); + public void onDisplayDeviceRemoved(DisplayDevice device); + } } diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java index 6d723f2..57002ff 100644 --- a/services/java/com/android/server/display/DisplayDevice.java +++ b/services/java/com/android/server/display/DisplayDevice.java @@ -18,8 +18,20 @@ package com.android.server.display; /** * Represents a physical display device such as the built-in display - * or an external monitor. + * an external monitor, or a WiFi display. */ public abstract class DisplayDevice { + /** + * Gets the display adapter that makes the display device available. + * + * @return The display adapter. + */ + public abstract DisplayAdapter getAdapter(); + + /** + * Gets information about the display device. + * + * @param outInfo The object to populate with the information. + */ public abstract void getInfo(DisplayDeviceInfo outInfo); } diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java index c60c2e9..9c0f964 100644 --- a/services/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/java/com/android/server/display/DisplayDeviceInfo.java @@ -21,6 +21,12 @@ package com.android.server.display; */ public final class DisplayDeviceInfo { /** + * Gets the name of the display device, which may be derived from + * EDID or other sources. The name may be displayed to the user. + */ + public String name; + + /** * The width of the display in its natural orientation, in pixels. * This value is not affected by display rotation. */ @@ -38,6 +44,7 @@ public final class DisplayDeviceInfo { public float yDpi; public void copyFrom(DisplayDeviceInfo other) { + name = other.name; width = other.width; height = other.height; refreshRate = other.refreshRate; @@ -46,9 +53,10 @@ public final class DisplayDeviceInfo { yDpi = other.yDpi; } + // For debugging purposes @Override public String toString() { - return width + " x " + height + ", " + refreshRate + " fps, " + return "\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, " + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"; } } diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 468bf21..2ebad1d 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -19,11 +19,10 @@ package com.android.server.display; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; +import android.hardware.display.DisplayManager; import android.hardware.display.IDisplayManager; import android.os.Binder; import android.os.SystemProperties; -import android.util.Slog; -import android.util.SparseArray; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; @@ -47,41 +46,27 @@ public final class DisplayManagerService extends IDisplayManager.Stub { private final Object mLock = new Object(); - private Context mContext; + private final Context mContext; private final boolean mHeadless; - private int mDisplayIdSeq = Display.DEFAULT_DISPLAY; - - /** All registered DisplayAdapters. */ private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>(); + private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo(); - /** All the DisplayAdapters showing the given displayId. */ - private final SparseArray<ArrayList<DisplayAdapter>> mLogicalToPhysicals = - new SparseArray<ArrayList<DisplayAdapter>>(); - - /** All the DisplayInfos in the system indexed by deviceId */ - private final SparseArray<DisplayInfo> mDisplayInfos = new SparseArray<DisplayInfo>(); - - private final ArrayList<DisplayCallback> mCallbacks = - new ArrayList<DisplayManagerService.DisplayCallback>(); - - public DisplayManagerService() { + public DisplayManagerService(Context context) { + mContext = context; mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1"); + registerDefaultDisplayAdapter(); } private void registerDefaultDisplayAdapter() { if (mHeadless) { - registerDisplayAdapter(new HeadlessDisplayAdapter()); + registerDisplayAdapter(new HeadlessDisplayAdapter(mContext)); } else { - registerDisplayAdapter(new SurfaceFlingerDisplayAdapter()); + registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext)); } } - public void setContext(Context context) { - mContext = context; - } - // FIXME: this isn't the right API for the long term public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) { // hardcoded assuming 720p touch screen plugged into HDMI and USB @@ -90,6 +75,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { info.height = 720; } + /** + * Returns true if the device is headless. + * + * @return True if the device is headless. + */ public boolean isHeadless() { return mHeadless; } @@ -101,12 +91,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub { */ public void setDisplayInfo(int displayId, DisplayInfo info) { synchronized (mLock) { - DisplayInfo localInfo = mDisplayInfos.get(displayId); - if (localInfo == null) { - localInfo = new DisplayInfo(); - mDisplayInfos.put(displayId, localInfo); + if (displayId != Display.DEFAULT_DISPLAY) { + throw new UnsupportedOperationException(); } - localInfo.copyFrom(info); + mDefaultDisplayInfo.copyFrom(info); } } @@ -118,177 +106,32 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) { synchronized (mLock) { - DisplayInfo localInfo = mDisplayInfos.get(displayId); - if (localInfo == null) { + if (displayId != Display.DEFAULT_DISPLAY) { return false; } - outInfo.copyFrom(localInfo); + outInfo.copyFrom(mDefaultDisplayInfo); return true; } } - /** - * Inform the service of a new physical display. A new logical displayId is created and the new - * physical display is immediately bound to it. Use removeAdapterFromDisplay to disconnect it. - * - * @param adapter The wrapper for information associated with the physical display. - */ - public void registerDisplayAdapter(DisplayAdapter adapter) { - - int displayId; - DisplayCallback[] callbacks; - - synchronized (mLock) { - displayId = mDisplayIdSeq; - do { - // Find the next unused displayId. (Pretend like it might ever wrap around). - mDisplayIdSeq++; - if (mDisplayIdSeq < 0) { - mDisplayIdSeq = Display.DEFAULT_DISPLAY + 1; - } - } while (mDisplayInfos.get(mDisplayIdSeq) != null); - - adapter.setDisplayId(displayId); - - createDisplayInfoLocked(displayId, adapter); - - ArrayList<DisplayAdapter> list = new ArrayList<DisplayAdapter>(); - list.add(adapter); - mLogicalToPhysicals.put(displayId, list); - - mDisplayAdapters.add(adapter); - callbacks = mCallbacks.toArray(new DisplayCallback[mCallbacks.size()]); - } - - for (int i = callbacks.length - 1; i >= 0; i--) { - callbacks[i].displayAdded(displayId); - } - - // TODO: Notify SurfaceFlinger of new addition. - } - - /** - * Connect a logical display to a physical display. Will remove the physical display from any - * logical display it is currently attached to. - * - * @param displayId The logical display. Will be created if it does not already exist. - * @param adapter The physical display. - */ - public void addAdapterToDisplay(int displayId, DisplayAdapter adapter) { - if (adapter == null) { - // TODO: Or throw NPE? - Slog.e(TAG, "addDeviceToDisplay: Attempt to add null adapter"); - return; - } - - synchronized (mLock) { - if (!mDisplayAdapters.contains(adapter)) { - // TOOD: Handle unregistered adapter with exception or return value. - Slog.e(TAG, "addDeviceToDisplay: Attempt to add an unregistered adapter"); - return; - } - - DisplayInfo displayInfo = mDisplayInfos.get(displayId); - if (displayInfo == null) { - createDisplayInfoLocked(displayId, adapter); - } - - Integer oldDisplayId = adapter.getDisplayId(); - if (oldDisplayId != Display.NO_DISPLAY) { - if (oldDisplayId == displayId) { - // adapter already added to displayId. - return; - } - - removeAdapterLocked(adapter); - } - - ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId); - if (list == null) { - list = new ArrayList<DisplayAdapter>(); - mLogicalToPhysicals.put(displayId, list); - } - list.add(adapter); - adapter.setDisplayId(displayId); - } - - // TODO: Notify SurfaceFlinger of new addition. - } - - /** - * Disconnect the physical display from whichever logical display it is attached to. - * @param adapter The physical display to detach. - */ - public void removeAdapterFromDisplay(DisplayAdapter adapter) { - if (adapter == null) { - // TODO: Or throw NPE? - return; - } - - synchronized (mLock) { - if (!mDisplayAdapters.contains(adapter)) { - // TOOD: Handle unregistered adapter with exception or return value. - Slog.e(TAG, "removeDeviceFromDisplay: Attempt to remove an unregistered adapter"); - return; + private void registerDisplayAdapter(DisplayAdapter adapter) { + mDisplayAdapters.add(adapter); + adapter.register(new DisplayAdapter.Listener() { + @Override + public void onDisplayDeviceAdded(DisplayDevice device) { + DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); + device.getInfo(deviceInfo); + copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo); } - removeAdapterLocked(adapter); - } - - // TODO: Notify SurfaceFlinger of removal. - } - - public void registerDisplayCallback(final DisplayCallback callback) { - synchronized (mLock) { - if (!mCallbacks.contains(callback)) { - mCallbacks.add(callback); + @Override + public void onDisplayDeviceRemoved(DisplayDevice device) { } - } + }); } - public void unregisterDisplayCallback(final DisplayCallback callback) { - synchronized (mLock) { - mCallbacks.remove(callback); - } - } - - /** - * Create a new logical DisplayInfo and fill it in with information from the physical display. - * @param displayId The logical identifier. - * @param adapter The physical display for initial values. - */ - private void createDisplayInfoLocked(int displayId, DisplayAdapter adapter) { - DisplayInfo displayInfo = new DisplayInfo(); - DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo(); - adapter.getDisplayDevice().getInfo(deviceInfo); - copyDisplayInfoFromDeviceInfo(displayInfo, deviceInfo); - mDisplayInfos.put(displayId, displayInfo); - } - - /** - * Disconnect a physical display from its logical display. If there are no more physical - * displays attached to the logical display, delete the logical display. - * @param adapter The physical display to detach. - */ - void removeAdapterLocked(DisplayAdapter adapter) { - int displayId = adapter.getDisplayId(); - adapter.setDisplayId(Display.NO_DISPLAY); - - ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId); - if (list != null) { - list.remove(adapter); - if (list.isEmpty()) { - mLogicalToPhysicals.remove(displayId); - // TODO: Keep count of Windows attached to logical display and don't delete if - // there are any outstanding. Also, what keeps the WindowManager from continuing - // to use the logical display? - mDisplayInfos.remove(displayId); - } - } - } - - private void copyDisplayInfoFromDeviceInfo(DisplayInfo displayInfo, - DisplayDeviceInfo deviceInfo) { + private void copyDisplayInfoFromDeviceInfo( + DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) { // Bootstrap the logical display using the physical display. displayInfo.appWidth = deviceInfo.width; displayInfo.appHeight = deviceInfo.height; @@ -319,19 +162,15 @@ public final class DisplayManagerService extends IDisplayManager.Stub { pw.println("Headless: " + mHeadless); - DisplayDeviceInfo info = new DisplayDeviceInfo(); - for (DisplayAdapter adapter : mDisplayAdapters) { - pw.println("Display for adapter " + adapter.getName() - + " assigned to Display " + adapter.getDisplayId()); - DisplayDevice device = adapter.getDisplayDevice(); - pw.print(" "); - device.getInfo(info); - pw.println(info); + synchronized (mLock) { + for (DisplayAdapter adapter : mDisplayAdapters) { + pw.println("Adapter: " + adapter.getName()); + } + + pw.println("Default display info: " + mDefaultDisplayInfo); } - } - public interface DisplayCallback { - public void displayAdded(int displayId); - public void displayRemoved(int displayId); + pw.println("Default display: " + + DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY)); } } diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java index 3eaf40f..17c2360 100644 --- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java +++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java @@ -16,15 +16,41 @@ package com.android.server.display; +import android.content.Context; import android.util.DisplayMetrics; /** * Provides a fake default display for headless systems. */ public final class HeadlessDisplayAdapter extends DisplayAdapter { - private final DisplayDevice mDefaultDisplay = new DisplayDevice() { + private final Context mContext; + private final HeadlessDisplayDevice mDefaultDisplayDevice; + + public HeadlessDisplayAdapter(Context context) { + mContext = context; + mDefaultDisplayDevice = new HeadlessDisplayDevice(); + } + + @Override + public String getName() { + return "HeadlessDisplayAdapter"; + } + + @Override + public void register(Listener listener) { + listener.onDisplayDeviceAdded(mDefaultDisplayDevice); + } + + private final class HeadlessDisplayDevice extends DisplayDevice { + @Override + public DisplayAdapter getAdapter() { + return HeadlessDisplayAdapter.this; + } + @Override public void getInfo(DisplayDeviceInfo outInfo) { + outInfo.name = mContext.getResources().getString( + com.android.internal.R.string.display_manager_built_in_display); outInfo.width = 640; outInfo.height = 480; outInfo.refreshRate = 60; @@ -32,15 +58,5 @@ public final class HeadlessDisplayAdapter extends DisplayAdapter { outInfo.xDpi = 160; outInfo.yDpi = 160; } - }; - - @Override - public String getName() { - return "HeadlessDisplayAdapter"; - } - - @Override - public DisplayDevice getDisplayDevice() { - return mDefaultDisplay; } } diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java index 539f7c1..9531acb 100644 --- a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java +++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java @@ -16,18 +16,21 @@ package com.android.server.display; +import android.content.Context; + /** * A display adapter for the displays managed by Surface Flinger. */ public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter { + private final Context mContext; + private final SurfaceFlingerDisplayDevice mDefaultDisplayDevice; + private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo); - private final DisplayDevice mDefaultDisplay = new DisplayDevice() { - @Override - public void getInfo(DisplayDeviceInfo outInfo) { - nativeGetDefaultDisplayDeviceInfo(outInfo); - } - }; + public SurfaceFlingerDisplayAdapter(Context context) { + mContext = context; + mDefaultDisplayDevice = new SurfaceFlingerDisplayDevice(); + } @Override public String getName() { @@ -35,7 +38,21 @@ public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter { } @Override - public DisplayDevice getDisplayDevice() { - return mDefaultDisplay; + public void register(Listener listener) { + listener.onDisplayDeviceAdded(mDefaultDisplayDevice); + } + + private final class SurfaceFlingerDisplayDevice extends DisplayDevice { + @Override + public DisplayAdapter getAdapter() { + return SurfaceFlingerDisplayAdapter.this; + } + + @Override + public void getInfo(DisplayDeviceInfo outInfo) { + outInfo.name = mContext.getResources().getString( + com.android.internal.R.string.display_manager_built_in_display); + nativeGetDefaultDisplayDeviceInfo(outInfo); + } } } diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index 21100e2..0b8ff62 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -1218,8 +1218,12 @@ public class InputManagerService extends IInputManager.Stub implements Watchdog. } // Native callback. - private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { - mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + private void notifySwitch(long whenNanos, int switchCode, int switchValue) { + switch (switchCode) { + case SW_LID: + mCallbacks.notifyLidSwitchChanged(whenNanos, switchValue == 0); + break; + } } // Native callback. diff --git a/services/java/com/android/server/location/GeofenceManager.java b/services/java/com/android/server/location/GeofenceManager.java index 338cd5d..26d9c15 100644 --- a/services/java/com/android/server/location/GeofenceManager.java +++ b/services/java/com/android/server/location/GeofenceManager.java @@ -34,9 +34,13 @@ import android.os.Bundle; import android.os.Looper; import android.os.PowerManager; import android.os.SystemClock; +import android.util.Log; + +import com.android.server.LocationManagerService; public class GeofenceManager implements LocationListener, PendingIntent.OnFinished { private static final String TAG = "GeofenceManager"; + private static final boolean D = LocationManagerService.D; /** * Assume a maximum land speed, as a heuristic to throttle location updates. @@ -49,6 +53,7 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish private final LocationManager mLocationManager; private final PowerManager.WakeLock mWakeLock; private final Looper mLooper; // looper thread to take location updates on + private final LocationBlacklist mBlacklist; private Object mLock = new Object(); @@ -56,12 +61,13 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish private Location mLastLocation; private List<GeofenceState> mFences = new LinkedList<GeofenceState>(); - public GeofenceManager(Context context) { + public GeofenceManager(Context context, LocationBlacklist blacklist) { mContext = context; mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mLooper = Looper.myLooper(); + mBlacklist = blacklist; LocationRequest request = new LocationRequest() .setQuality(LocationRequest.POWER_NONE) @@ -145,6 +151,12 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish removeExpiredFencesLocked(); for (GeofenceState state : mFences) { + if (mBlacklist.isBlacklisted(state.mPackageName)) { + if (D) Log.d(TAG, "skipping geofence processing for blacklisted app: " + + state.mPackageName); + continue; + } + int event = state.processLocation(location); if ((event & GeofenceState.FLAG_ENTER) != 0) { enterIntents.add(state.mIntent); diff --git a/services/java/com/android/server/location/LocationBlacklist.java b/services/java/com/android/server/location/LocationBlacklist.java new file mode 100644 index 0000000..71fa9f9 --- /dev/null +++ b/services/java/com/android/server/location/LocationBlacklist.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.android.server.location; + +import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.provider.Settings; +import android.util.Log; +import android.util.Slog; + +import com.android.server.LocationManagerService; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Allows applications to be blacklisted from location updates at run-time. + * + * This is a silent blacklist. Applications can still call Location Manager + * API's, but they just won't receive any locations. + */ +public final class LocationBlacklist extends ContentObserver { + private static final String TAG = "LocationBlacklist"; + private static final boolean D = LocationManagerService.D; + private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist"; + private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist"; + + private final Context mContext; + private final Object mLock = new Object(); + + // all fields below synchronized on mLock + private String[] mWhitelist = new String[0]; + private String[] mBlacklist = new String[0]; + + public LocationBlacklist(Context context, Handler handler) { + super(handler); + mContext = context; + } + + public void init() { + mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( + BLACKLIST_CONFIG_NAME), false, this); +// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor( +// WHITELIST_CONFIG_NAME), false, this); + reloadBlacklist(); + } + + private void reloadBlacklist() { + String blacklist[] = getStringArray(BLACKLIST_CONFIG_NAME); + String whitelist[] = getStringArray(WHITELIST_CONFIG_NAME); + synchronized (mLock) { + mWhitelist = whitelist; + Slog.i(TAG, "whitelist: " + Arrays.toString(mWhitelist)); + mBlacklist = blacklist; + Slog.i(TAG, "blacklist: " + Arrays.toString(mBlacklist)); + } + } + + /** + * Return true if in blacklist + * (package name matches blacklist, and does not match whitelist) + */ + public boolean isBlacklisted(String packageName) { + synchronized (mLock) { + for (String black : mBlacklist) { + if (packageName.startsWith(black)) { + if (inWhitelist(packageName)) { + continue; + } else { + if (D) Log.d(TAG, "dropping location (blacklisted): " + + packageName + " matches " + black); + return true; + } + } + } + } + return false; + } + + /** + * Return true if any of packages are in whitelist + */ + private boolean inWhitelist(String pkg) { + synchronized (mLock) { + for (String white : mWhitelist) { + if (pkg.startsWith(white)) return true; + } + } + return false; + } + + @Override + public void onChange(boolean selfChange) { + reloadBlacklist(); + } + + private String[] getStringArray(String key) { + String flatString = Settings.Secure.getString(mContext.getContentResolver(), key); + if (flatString == null) { + return new String[0]; + } + String[] splitStrings = flatString.split(","); + ArrayList<String> result = new ArrayList<String>(); + for (String pkg : splitStrings) { + pkg = pkg.trim(); + if (pkg.isEmpty()) { + continue; + } + result.add(pkg); + } + return result.toArray(new String[result.size()]); + } + + public void dump(PrintWriter pw) { + pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" + + Arrays.toString(mBlacklist)); + } +} diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 0d6e08d..be82b34 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -79,6 +79,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.content.pm.ManifestDigest; +import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.net.Uri; @@ -2422,6 +2423,9 @@ public class PackageManagerService extends IPackageManager.Stub { final int M = prefs.size(); for (int i=0; i<M; i++) { final PreferredActivity pa = prefs.get(i); + if (pa.mUserId != userId) { + continue; + } if (pa.mPref.mMatch != match) { continue; } @@ -5348,7 +5352,17 @@ public class PackageManagerService extends IPackageManager.Stub { public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null); + VerificationParams verificationParams = new VerificationParams(verificationURI, null, null, + manifestDigest); + installPackageWithVerificationAndEncryption(packageURI, observer, flags, + installerPackageName, verificationParams, encryptionParams); + } + + public void installPackageWithVerificationAndEncryption(Uri packageURI, + IPackageInstallObserver observer, int flags, String installerPackageName, + VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, + null); final int uid = Binder.getCallingUid(); @@ -5365,7 +5379,7 @@ public class PackageManagerService extends IPackageManager.Stub { final Message msg = mHandler.obtainMessage(INIT_COPY); msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName, - verificationURI, manifestDigest, encryptionParams); + verificationParams, encryptionParams); mHandler.sendMessage(msg); } @@ -5795,8 +5809,7 @@ public class PackageManagerService extends IPackageManager.Stub { private final Uri mPackageURI; final String installerPackageName; - final Uri verificationURI; - final ManifestDigest manifestDigest; + final VerificationParams verificationParams; private InstallArgs mArgs; private int mRet; private File mTempPackage; @@ -5804,17 +5817,23 @@ public class PackageManagerService extends IPackageManager.Stub { InstallParams(Uri packageURI, IPackageInstallObserver observer, int flags, - String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest, + String installerPackageName, VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) { this.mPackageURI = packageURI; this.flags = flags; this.observer = observer; this.installerPackageName = installerPackageName; - this.verificationURI = verificationURI; - this.manifestDigest = manifestDigest; + this.verificationParams = verificationParams; this.encryptionParams = encryptionParams; } + public ManifestDigest getManifestDigest() { + if (verificationParams == null) { + return null; + } + return verificationParams.getManifestDigest(); + } + private int installLocationPolicy(PackageInfoLite pkgLite, int flags) { String packageName = pkgLite.packageName; int installLocation = pkgLite.installLocation; @@ -6003,9 +6022,19 @@ public class PackageManagerService extends IPackageManager.Stub { verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags); - if (verificationURI != null) { - verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI, - verificationURI); + if (verificationParams != null) { + if (verificationParams.getVerificationURI() != null) { + verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI, + verificationParams.getVerificationURI()); + } + if (verificationParams.getOriginatingURI() != null) { + verification.putExtra(Intent.EXTRA_ORIGINATING_URI, + verificationParams.getOriginatingURI()); + } + if (verificationParams.getReferrer() != null) { + verification.putExtra(Intent.EXTRA_REFERRER, + verificationParams.getReferrer()); + } } final PackageVerificationState verificationState = new PackageVerificationState( @@ -6341,7 +6370,7 @@ public class PackageManagerService extends IPackageManager.Stub { FileInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, - params.installerPackageName, params.manifestDigest); + params.installerPackageName, params.getManifestDigest()); } FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) { @@ -6628,7 +6657,7 @@ public class PackageManagerService extends IPackageManager.Stub { AsecInstallArgs(InstallParams params) { super(params.getPackageUri(), params.observer, params.flags, - params.installerPackageName, params.manifestDigest); + params.installerPackageName, params.getManifestDigest()); } AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath, @@ -7645,7 +7674,7 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids); } } - clearPackagePreferredActivitiesLPw(deletedPs.name); + clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL); } } // can downgrade to reader @@ -8112,26 +8141,28 @@ public class PackageManagerService extends IPackageManager.Stub { } public void addPreferredActivity(IntentFilter filter, int match, - ComponentName[] set, ComponentName activity) { + ComponentName[] set, ComponentName activity, int userId) { // writer + int callingUid = Binder.getCallingUid(); + checkValidCaller(callingUid, userId); synchronized (mPackages) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { - if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid()) + if (getUidTargetSdkVersionLockedLPr(callingUid) < Build.VERSION_CODES.FROYO) { Slog.w(TAG, "Ignoring addPreferredActivity() from uid " - + Binder.getCallingUid()); + + callingUid); return; } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); } - - Slog.i(TAG, "Adding preferred activity " + activity + ":"); + + Slog.i(TAG, "Adding preferred activity " + activity + " for user " + userId + " :"); filter.dump(new LogPrinter(Log.INFO, TAG), " "); mSettings.mPreferredActivities.addFilter( - new PreferredActivity(filter, match, set, activity)); + new PreferredActivity(filter, match, set, activity, userId)); scheduleWriteSettingsLocked(); } } @@ -8167,13 +8198,15 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); } - + + final int callingUserId = UserHandle.getCallingUserId(); ArrayList<PreferredActivity> removed = null; Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); String action = filter.getAction(0); String category = filter.getCategory(0); while (it.hasNext()) { PreferredActivity pa = it.next(); + if (pa.mUserId != callingUserId) continue; if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) { if (removed == null) { removed = new ArrayList<PreferredActivity>(); @@ -8189,7 +8222,7 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.mPreferredActivities.removeFilter(pa); } } - addPreferredActivity(filter, match, set, activity); + addPreferredActivity(filter, match, set, activity, callingUserId); } } @@ -8213,17 +8246,21 @@ public class PackageManagerService extends IPackageManager.Stub { } } - if (clearPackagePreferredActivitiesLPw(packageName)) { + if (clearPackagePreferredActivitiesLPw(packageName, UserHandle.getCallingUserId())) { scheduleWriteSettingsLocked(); } } } - boolean clearPackagePreferredActivitiesLPw(String packageName) { + /** This method takes a specific user id as well as UserHandle.USER_ALL. */ + boolean clearPackagePreferredActivitiesLPw(String packageName, int userId) { ArrayList<PreferredActivity> removed = null; Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); while (it.hasNext()) { PreferredActivity pa = it.next(); + if (userId != UserHandle.USER_ALL && pa.mUserId != userId) { + continue; + } if (pa.mPref.mComponent.getPackageName().equals(packageName)) { if (removed == null) { removed = new ArrayList<PreferredActivity>(); @@ -8245,11 +8282,15 @@ public class PackageManagerService extends IPackageManager.Stub { List<ComponentName> outActivities, String packageName) { int num = 0; + final int userId = UserHandle.getCallingUserId(); // reader synchronized (mPackages) { final Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator(); while (it.hasNext()) { final PreferredActivity pa = it.next(); + if (pa.mUserId != userId) { + continue; + } if (packageName == null || pa.mPref.mComponent.getPackageName().equals(packageName)) { if (outFilters != null) { diff --git a/services/java/com/android/server/pm/PreferredActivity.java b/services/java/com/android/server/pm/PreferredActivity.java index b100eb1..5539e84 100644 --- a/services/java/com/android/server/pm/PreferredActivity.java +++ b/services/java/com/android/server/pm/PreferredActivity.java @@ -33,22 +33,38 @@ class PreferredActivity extends IntentFilter implements PreferredComponent.Callb private static final String TAG = "PreferredActivity"; private static final boolean DEBUG_FILTERS = false; + static final String ATTR_USER_ID = "userId"; final PreferredComponent mPref; + final int mUserId; PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { + this(filter, match, set, activity, 0); + } + + PreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity, + int userId) { super(filter); + mUserId = userId; mPref = new PreferredComponent(this, match, set, activity); } PreferredActivity(XmlPullParser parser) throws XmlPullParserException, IOException { + String userIdString = parser.getAttributeValue(null, ATTR_USER_ID); + if (userIdString != null && userIdString.length() > 0) { + mUserId = Integer.parseInt(userIdString); + } else { + // Old format with no userId specified - assume primary user + mUserId = 0; + } mPref = new PreferredComponent(this, parser); } public void writeToXml(XmlSerializer serializer) throws IOException { + serializer.attribute(null, ATTR_USER_ID, Integer.toString(mUserId)); mPref.writeToXml(serializer); serializer.startTag(null, "filter"); - super.writeToXml(serializer); + super.writeToXml(serializer); serializer.endTag(null, "filter"); } diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index a828864..c292bbc 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -506,6 +506,8 @@ public class UserManagerService extends IUserManager.Stub { Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userInfo.id); mContext.sendBroadcast(addedIntent, android.Manifest.permission.MANAGE_USERS); + mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_BOOT_COMPLETED), + new UserHandle(userInfo.id)); } return userInfo; } diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java index f3183f8..cf12b20 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/java/com/android/server/power/DisplayPowerController.java @@ -27,6 +27,7 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.SystemSensorManager; +import android.hardware.display.DisplayManager; import android.os.AsyncTask; import android.os.Handler; import android.os.Looper; @@ -35,6 +36,7 @@ import android.os.SystemClock; import android.util.Slog; import android.util.Spline; import android.util.TimeUtils; +import android.view.Display; import java.io.PrintWriter; import java.io.StringWriter; @@ -73,8 +75,8 @@ final class DisplayPowerController { // If true, uses the electron beam on animation. // We might want to turn this off if we cannot get a guarantee that the screen // actually turns on and starts showing new content after the call to set the - // screen state returns. - private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = true; + // screen state returns. Playing the animation can also be somewhat slow. + private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false; private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300; private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600; @@ -98,15 +100,15 @@ final class DisplayPowerController { // Brightness animation ramp rate in brightness units per second. private static final int BRIGHTNESS_RAMP_RATE_FAST = 200; - private static final int BRIGHTNESS_RAMP_RATE_SLOW = 50; + private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; // Filter time constant in milliseconds for computing a moving // average of light samples. Different constants are used // to calculate the average light level when adapting to brighter or // dimmer environments. // This parameter only controls the filtering of light samples. - private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 500; - private static final long DIMMING_LIGHT_TIME_CONSTANT = 2000; + private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 600; + private static final long DIMMING_LIGHT_TIME_CONSTANT = 4000; // Stability requirements in milliseconds for accepting a new brightness // level. This is used for debouncing the light sensor. Different constants @@ -428,7 +430,8 @@ final class DisplayPowerController { private void initialize() { final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; - mPowerState = new DisplayPowerState(new ElectronBeam(), + Display display = DisplayManager.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); + mPowerState = new DisplayPowerState(new ElectronBeam(display), new PhotonicModulator(executor, mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mSuspendBlocker)); @@ -476,11 +479,13 @@ final class DisplayPowerController { if (mPowerRequest == null) { mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked); mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked; + mPendingWaitForNegativeProximityLocked = false; mPendingRequestChangedLocked = false; mustInitialize = true; } else if (mPendingRequestChangedLocked) { mPowerRequest.copyFrom(mPendingRequestLocked); mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked; + mPendingWaitForNegativeProximityLocked = false; mPendingRequestChangedLocked = false; mDisplayReadyLocked = false; } @@ -493,24 +498,33 @@ final class DisplayPowerController { initialize(); } - // Clear a request to wait for negative proximity if needed. - if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_OFF - || mProximity == PROXIMITY_NEGATIVE - || mProximitySensor == null) { - mWaitingForNegativeProximity = false; - } - - // Turn on the proximity sensor if needed. + // Apply the proximity sensor. if (mProximitySensor != null) { - setProximitySensorEnabled(mPowerRequest.useProximitySensor - || mWaitingForNegativeProximity); - if (mProximitySensorEnabled && mProximity == PROXIMITY_POSITIVE) { - mScreenOffBecauseOfProximity = true; - setScreenOn(false); - } else if (mScreenOffBecauseOfProximity) { + if (mPowerRequest.useProximitySensor + && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { + setProximitySensorEnabled(true); + if (!mScreenOffBecauseOfProximity + && mProximity == PROXIMITY_POSITIVE) { + mScreenOffBecauseOfProximity = true; + setScreenOn(false); + } + } else if (mWaitingForNegativeProximity + && mScreenOffBecauseOfProximity + && mProximity == PROXIMITY_POSITIVE + && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) { + setProximitySensorEnabled(true); + } else { + setProximitySensorEnabled(false); + mWaitingForNegativeProximity = false; + } + if (mScreenOffBecauseOfProximity + && mProximity != PROXIMITY_POSITIVE) { mScreenOffBecauseOfProximity = false; + setScreenOn(true); sendOnProximityNegative(); } + } else { + mWaitingForNegativeProximity = false; } // Turn on the light sensor if needed. diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java index 5472148..2d24249 100644 --- a/services/java/com/android/server/power/ElectronBeam.java +++ b/services/java/com/android/server/power/ElectronBeam.java @@ -33,7 +33,6 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceSession; -import android.view.WindowManagerImpl; import java.io.PrintWriter; import java.nio.ByteBuffer; @@ -68,6 +67,7 @@ final class ElectronBeam { private boolean mPrepared; private boolean mWarmUp; + private final Display mDisplay; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private int mDisplayLayerStack; // layer stack associated with primary display private int mDisplayRotation; @@ -90,7 +90,8 @@ final class ElectronBeam { private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8); private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8); - public ElectronBeam() { + public ElectronBeam(Display display) { + mDisplay = display; } /** @@ -109,9 +110,8 @@ final class ElectronBeam { mWarmUp = warmUp; // Get the display size and adjust it for rotation. - Display display = WindowManagerImpl.getDefault().getDefaultDisplay(); - display.getDisplayInfo(mDisplayInfo); - mDisplayLayerStack = display.getDisplayId(); + mDisplay.getDisplayInfo(mDisplayInfo); + mDisplayLayerStack = mDisplay.getLayerStack(); mDisplayRotation = mDisplayInfo.rotation; if (mDisplayRotation == Surface.ROTATION_90 || mDisplayRotation == Surface.ROTATION_270) { diff --git a/services/java/com/android/server/usb/UsbDebuggingManager.java b/services/java/com/android/server/usb/UsbDebuggingManager.java new file mode 100644 index 0000000..a3b45c7 --- /dev/null +++ b/services/java/com/android/server/usb/UsbDebuggingManager.java @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions an + * limitations under the License. + */ + +package com.android.server.usb; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.os.SystemClock; +import android.util.Slog; +import android.util.Base64; + +import java.lang.Thread; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.security.MessageDigest; +import java.util.Arrays; + +public class UsbDebuggingManager implements Runnable { + private static final String TAG = "UsbDebuggingManager"; + private static final boolean DEBUG = false; + + private final String ADBD_SOCKET = "adbd"; + private final String ADB_DIRECTORY = "misc/adb"; + private final String ADB_KEYS_FILE = "adb_keys"; + private final int BUFFER_SIZE = 4096; + + private final Context mContext; + private final Thread mThread; + private final Handler mHandler; + private final HandlerThread mHandlerThread; + private boolean mAdbEnabled = false; + private String mFingerprints; + private LocalSocket mSocket = null; + private OutputStream mOutputStream = null; + + public UsbDebuggingManager(Context context) { + mThread = new Thread(this); + mHandlerThread = new HandlerThread("UsbDebuggingHandler"); + mHandlerThread.start(); + mHandler = new UsbDebuggingHandler(mHandlerThread.getLooper()); + mContext = context; + } + + private void listenToSocket() throws IOException { + try { + byte[] buffer = new byte[BUFFER_SIZE]; + LocalSocketAddress address = new LocalSocketAddress(ADBD_SOCKET, + LocalSocketAddress.Namespace.RESERVED); + InputStream inputStream = null; + + mSocket = new LocalSocket(); + mSocket.connect(address); + + mOutputStream = mSocket.getOutputStream(); + inputStream = mSocket.getInputStream(); + + while (true) { + int count = inputStream.read(buffer); + if (count < 0) { + Slog.e(TAG, "got " + count + " reading"); + break; + } + + if (buffer[0] == 'P' && buffer[1] == 'K') { + String key = new String(Arrays.copyOfRange(buffer, 2, count)); + Slog.d(TAG, "Received public key: " + key); + Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_CONFIRM); + msg.obj = key; + mHandler.sendMessage(msg); + } + else { + Slog.e(TAG, "Wrong message: " + (new String(Arrays.copyOfRange(buffer, 0, 2)))); + break; + } + } + } catch (IOException ex) { + Slog.e(TAG, "Communication error: ", ex); + throw ex; + } finally { + closeSocket(); + } + } + + @Override + public void run() { + while (mAdbEnabled) { + try { + listenToSocket(); + } catch (Exception e) { + /* Don't loop too fast if adbd dies, before init restarts it */ + SystemClock.sleep(1000); + } + } + } + + private void closeSocket() { + try { + mOutputStream.close(); + } catch (IOException e) { + Slog.e(TAG, "Failed closing output stream: " + e); + } + + try { + mSocket.close(); + } catch (IOException ex) { + Slog.e(TAG, "Failed closing socket: " + ex); + } + } + + private void sendResponse(String msg) { + if (mOutputStream != null) { + try { + mOutputStream.write(msg.getBytes()); + } + catch (IOException ex) { + Slog.e(TAG, "Failed to write response:", ex); + } + } + } + + class UsbDebuggingHandler extends Handler { + private static final int MESSAGE_ADB_ENABLED = 1; + private static final int MESSAGE_ADB_DISABLED = 2; + private static final int MESSAGE_ADB_ALLOW = 3; + private static final int MESSAGE_ADB_DENY = 4; + private static final int MESSAGE_ADB_CONFIRM = 5; + + public UsbDebuggingHandler(Looper looper) { + super(looper); + } + + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_ADB_ENABLED: + if (mAdbEnabled) + break; + + mAdbEnabled = true; + + mThread.start(); + + break; + + case MESSAGE_ADB_DISABLED: + if (!mAdbEnabled) + break; + + mAdbEnabled = false; + closeSocket(); + + try { + mThread.join(); + } catch (Exception ex) { + } + + mOutputStream = null; + mSocket = null; + + case MESSAGE_ADB_ALLOW: { + String key = (String)msg.obj; + String fingerprints = getFingerprints(key); + + if (!fingerprints.equals(mFingerprints)) { + Slog.e(TAG, "Fingerprints do not match. Got " + + fingerprints + ", expected " + mFingerprints); + break; + } + + if (msg.arg1 == 1) { + writeKey(key); + } + + sendResponse("OK"); + break; + } + + case MESSAGE_ADB_DENY: + sendResponse("NO"); + break; + + case MESSAGE_ADB_CONFIRM: { + String key = (String)msg.obj; + mFingerprints = getFingerprints(key); + showConfirmationDialog(key, mFingerprints); + break; + } + } + } + } + + private String getFingerprints(String key) { + String hex = "0123456789ABCDEF"; + StringBuilder sb = new StringBuilder(); + MessageDigest digester; + + try { + digester = MessageDigest.getInstance("MD5"); + } catch (Exception ex) { + Slog.e(TAG, "Error getting digester: " + ex); + return ""; + } + + byte[] base64_data = key.split("\\s+")[0].getBytes(); + byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT)); + + for (int i = 0; i < digest.length; i++) { + sb.append(hex.charAt((digest[i] >> 4) & 0xf)); + sb.append(hex.charAt(digest[i] & 0xf)); + if (i < digest.length - 1) + sb.append(":"); + } + return sb.toString(); + } + + private void showConfirmationDialog(String key, String fingerprints) { + Intent dialogIntent = new Intent(); + + dialogIntent.setClassName("com.android.systemui", + "com.android.systemui.usb.UsbDebuggingActivity"); + dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + dialogIntent.putExtra("key", key); + dialogIntent.putExtra("fingerprints", fingerprints); + try { + mContext.startActivity(dialogIntent); + } catch (ActivityNotFoundException e) { + Slog.e(TAG, "unable to start UsbDebuggingActivity"); + } + } + + private void writeKey(String key) { + File dataDir = Environment.getDataDirectory(); + File adbDir = new File(dataDir, ADB_DIRECTORY); + + if (!adbDir.exists()) { + Slog.e(TAG, "ADB data directory does not exist"); + return; + } + + try { + File keyFile = new File(adbDir, ADB_KEYS_FILE); + + if (!keyFile.exists()) { + keyFile.createNewFile(); + FileUtils.setPermissions(keyFile.toString(), + FileUtils.S_IRUSR | FileUtils.S_IWUSR | + FileUtils.S_IRGRP, -1, -1); + } + + FileOutputStream fo = new FileOutputStream(keyFile, true); + fo.write(key.getBytes()); + fo.write('\n'); + fo.close(); + } + catch (IOException ex) { + Slog.e(TAG, "Error writing key:" + ex); + } + } + + + public void setAdbEnabled(boolean enabled) { + mHandler.sendEmptyMessage(enabled ? UsbDebuggingHandler.MESSAGE_ADB_ENABLED + : UsbDebuggingHandler.MESSAGE_ADB_DISABLED); + } + + public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { + Message msg = mHandler.obtainMessage(UsbDebuggingHandler.MESSAGE_ADB_ALLOW); + msg.arg1 = alwaysAllow ? 1 : 0; + msg.obj = publicKey; + mHandler.sendMessage(msg); + } + + public void denyUsbDebugging() { + mHandler.sendEmptyMessage(UsbDebuggingHandler.MESSAGE_ADB_DENY); + } + + + public void dump(FileDescriptor fd, PrintWriter pw) { + pw.println(" USB Debugging State:"); + pw.println(" Connected to adbd: " + (mOutputStream != null)); + pw.println(" Last key received: " + mFingerprints); + pw.println(" User keys:"); + try { + pw.println(FileUtils.readTextFile(new File("/data/misc/adb/adb_keys"), 0, null)); + } catch (IOException e) { + pw.println("IOException: " + e); + } + pw.println(" System keys:"); + try { + pw.println(FileUtils.readTextFile(new File("/adb_keys"), 0, null)); + } catch (IOException e) { + pw.println("IOException: " + e); + } + } +} diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index a115345..ddecf14 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -114,6 +114,7 @@ public class UsbDeviceManager { private boolean mAudioSourceEnabled; private Map<String, List<Pair<String, String>>> mOemModeMap; private String[] mAccessoryStrings; + private UsbDebuggingManager mDebuggingManager; private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { @@ -166,6 +167,10 @@ public class UsbDeviceManager { if (DEBUG) Slog.d(TAG, "accessory attached at boot"); startAccessoryMode(); } + + if ("1".equals(SystemProperties.get("ro.adb.secure"))) { + mDebuggingManager = new UsbDebuggingManager(context); + } } public void systemReady() { @@ -425,6 +430,9 @@ public class UsbDeviceManager { setEnabledFunctions(mDefaultFunctions, true); updateAdbNotification(); } + if (mDebuggingManager != null) { + mDebuggingManager.setAdbEnabled(mAdbEnabled); + } } private void setEnabledFunctions(String functions, boolean makeDefault) { @@ -601,6 +609,9 @@ public class UsbDeviceManager { if (mCurrentAccessory != null) { mSettingsManager.accessoryAttached(mCurrentAccessory); } + if (mDebuggingManager != null) { + mDebuggingManager.setAdbEnabled(mAdbEnabled); + } break; } } @@ -802,10 +813,25 @@ public class UsbDeviceManager { return usbFunctions; } + public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { + if (mDebuggingManager != null) { + mDebuggingManager.allowUsbDebugging(alwaysAllow, publicKey); + } + } + + public void denyUsbDebugging() { + if (mDebuggingManager != null) { + mDebuggingManager.denyUsbDebugging(); + } + } + public void dump(FileDescriptor fd, PrintWriter pw) { if (mHandler != null) { mHandler.dump(fd, pw); } + if (mDebuggingManager != null) { + mDebuggingManager.dump(fd, pw); + } } private native String[] nativeGetAccessoryStrings(); diff --git a/services/java/com/android/server/usb/UsbService.java b/services/java/com/android/server/usb/UsbService.java index 0205ef8..bebcd56 100644 --- a/services/java/com/android/server/usb/UsbService.java +++ b/services/java/com/android/server/usb/UsbService.java @@ -164,6 +164,16 @@ public class UsbService extends IUsbManager.Stub { } } + public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); + } + + public void denyUsbDebugging() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.denyUsbDebugging(); + } + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java index 691e2aa..c25f010 100644 --- a/services/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/java/com/android/server/wm/AppWindowAnimator.java @@ -47,7 +47,7 @@ public class AppWindowAnimator { final Transformation thumbnailTransformation = new Transformation(); /** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */ - ArrayList<WindowStateAnimator> mAllAppWinAnimators; + ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>(); static final Animation sDummyAnimation = new DummyAnimation(); diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index 142c60d..7d85d89 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -42,6 +42,7 @@ class ScreenRotationAnimation { static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200; final Context mContext; + final Display mDisplay; Surface mSurface; BlackFrame mCustomBlackFrame; BlackFrame mExitingBlackFrame; @@ -186,9 +187,10 @@ class ScreenRotationAnimation { pw.println(); } - public ScreenRotationAnimation(Context context, SurfaceSession session, + public ScreenRotationAnimation(Context context, Display display, SurfaceSession session, boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) { mContext = context; + mDisplay = display; // Screenshot does NOT include rotation! if (originalRotation == Surface.ROTATION_90 @@ -213,13 +215,13 @@ class ScreenRotationAnimation { try { try { if (WindowManagerService.DEBUG_SURFACE_TRACE) { - mSurface = new SurfaceTrace(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY, - mWidth, mHeight, - PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); + mSurface = new SurfaceTrace(session, 0, "FreezeSurface", + mDisplay.getLayerStack(), mWidth, mHeight, + PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); } else { - mSurface = new Surface(session, 0, "FreezeSurface", Display.DEFAULT_DISPLAY, - mWidth, mHeight, - PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); + mSurface = new Surface(session, 0, "FreezeSurface", + mDisplay.getLayerStack(), mWidth, mHeight, + PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN); } if (!mSurface.isValid()) { // Screenshot failed, punt. diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java index 4b072c3..775aa0f 100644 --- a/services/java/com/android/server/wm/StrictModeFlash.java +++ b/services/java/com/android/server/wm/StrictModeFlash.java @@ -22,8 +22,6 @@ import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Region; -import android.util.DisplayMetrics; -import android.util.Slog; import android.view.Display; import android.view.Surface; import android.view.SurfaceSession; @@ -39,7 +37,7 @@ class StrictModeFlash { public StrictModeFlash(Display display, SurfaceSession session) { try { - mSurface = new Surface(session, 0, "StrictModeFlash", Display.DEFAULT_DISPLAY, + mSurface = new Surface(session, 0, "StrictModeFlash", display.getLayerStack(), 1, 1, PixelFormat.TRANSLUCENT, 0); } catch (Surface.OutOfResourcesException e) { return; diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java index 12076d8..5901cc8 100644 --- a/services/java/com/android/server/wm/Watermark.java +++ b/services/java/com/android/server/wm/Watermark.java @@ -35,6 +35,7 @@ import android.view.Surface.OutOfResourcesException; * Displays a watermark on top of the window manager's windows. */ class Watermark { + final Display mDisplay; final String[] mTokens; final String mText; final Paint mTextPaint; @@ -50,7 +51,7 @@ class Watermark { int mLastDH; boolean mDrawNeeded; - Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) { + Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) { if (false) { Log.i(WindowManagerService.TAG, "*********************** WATERMARK"); for (int i=0; i<tokens.length; i++) { @@ -58,6 +59,7 @@ class Watermark { } } + mDisplay = display; mTokens = tokens; StringBuilder builder = new StringBuilder(32); @@ -112,7 +114,7 @@ class Watermark { try { mSurface = new Surface(session, 0, - "WatermarkSurface", Display.DEFAULT_DISPLAY, + "WatermarkSurface", mDisplay.getLayerStack(), 1, 1, PixelFormat.TRANSLUCENT, 0); mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100); mSurface.setPosition(0, 0); diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 0dbe692..1defa49 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -190,8 +190,8 @@ public class WindowAnimator { for (int i = 0; i < N; i++) { final AppWindowAnimParams params = layoutToAnim.mAppWindowAnimParams.get(i); AppWindowAnimator appAnimator = params.mAppAnimator; - appAnimator.mAllAppWinAnimators = - new ArrayList<WindowStateAnimator>(params.mWinAnimators); + appAnimator.mAllAppWinAnimators.clear(); + appAnimator.mAllAppWinAnimators.addAll(params.mWinAnimators); mAppAnimators.add(appAnimator); } } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index c1884da..98adf38 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -127,7 +127,7 @@ import android.view.SurfaceSession; import android.view.View; import android.view.ViewTreeObserver; import android.view.WindowManager; -import android.view.WindowManagerImpl; +import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicy; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerPolicy.FakeWindow; @@ -2141,7 +2141,7 @@ public class WindowManagerService extends IWindowManager.Stub WindowManager.LayoutParams attrs, int viewVisibility, int displayId, Rect outContentInsets, InputChannel outInputChannel) { int res = mPolicy.checkAddPermission(attrs); - if (res != WindowManagerImpl.ADD_OKAY) { + if (res != WindowManagerGlobal.ADD_OKAY) { return res; } @@ -2157,7 +2157,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mWindowMap.containsKey(client.asBinder())) { Slog.w(TAG, "Window " + client + " is already added"); - return WindowManagerImpl.ADD_DUPLICATE_ADD; + return WindowManagerGlobal.ADD_DUPLICATE_ADD; } if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) { @@ -2165,13 +2165,13 @@ public class WindowManagerService extends IWindowManager.Stub if (attachedWindow == null) { Slog.w(TAG, "Attempted to add window with token that is not a window: " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN; + return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; } if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) { Slog.w(TAG, "Attempted to add window with token that is a sub-window: " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN; + return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN; } } @@ -2182,22 +2182,22 @@ public class WindowManagerService extends IWindowManager.Stub && attrs.type <= LAST_APPLICATION_WINDOW) { Slog.w(TAG, "Attempted to add application window with unknown token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (attrs.type == TYPE_INPUT_METHOD) { Slog.w(TAG, "Attempted to add input method window with unknown token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (attrs.type == TYPE_WALLPAPER) { Slog.w(TAG, "Attempted to add wallpaper window with unknown token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } if (attrs.type == TYPE_DREAM) { Slog.w(TAG, "Attempted to add Dream window with unknown token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } token = new WindowToken(this, attrs.token, -1, false); addToken = true; @@ -2207,35 +2207,35 @@ public class WindowManagerService extends IWindowManager.Stub if (atoken == null) { Slog.w(TAG, "Attempted to add window with non-application token " + token + ". Aborting."); - return WindowManagerImpl.ADD_NOT_APP_TOKEN; + return WindowManagerGlobal.ADD_NOT_APP_TOKEN; } else if (atoken.removed) { Slog.w(TAG, "Attempted to add window with exiting application token " + token + ". Aborting."); - return WindowManagerImpl.ADD_APP_EXITING; + return WindowManagerGlobal.ADD_APP_EXITING; } if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) { // No need for this guy! if (localLOGV) Slog.v( TAG, "**** NO NEED TO START: " + attrs.getTitle()); - return WindowManagerImpl.ADD_STARTING_NOT_NEEDED; + return WindowManagerGlobal.ADD_STARTING_NOT_NEEDED; } } else if (attrs.type == TYPE_INPUT_METHOD) { if (token.windowType != TYPE_INPUT_METHOD) { Slog.w(TAG, "Attempted to add input method window with bad token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } else if (attrs.type == TYPE_WALLPAPER) { if (token.windowType != TYPE_WALLPAPER) { Slog.w(TAG, "Attempted to add wallpaper window with bad token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } else if (attrs.type == TYPE_DREAM) { if (token.windowType != TYPE_DREAM) { Slog.w(TAG, "Attempted to add Dream window with bad token " + attrs.token + ". Aborting."); - return WindowManagerImpl.ADD_BAD_APP_TOKEN; + return WindowManagerGlobal.ADD_BAD_APP_TOKEN; } } @@ -2247,13 +2247,13 @@ public class WindowManagerService extends IWindowManager.Stub // continue. Slog.w(TAG, "Adding window client " + client.asBinder() + " that is dead, aborting."); - return WindowManagerImpl.ADD_APP_EXITING; + return WindowManagerGlobal.ADD_APP_EXITING; } mPolicy.adjustWindowParamsLw(win.mAttrs); res = mPolicy.prepareAddWindowLw(win, attrs); - if (res != WindowManagerImpl.ADD_OKAY) { + if (res != WindowManagerGlobal.ADD_OKAY) { return res; } @@ -2269,7 +2269,7 @@ public class WindowManagerService extends IWindowManager.Stub // From now on, no exceptions or errors allowed! - res = WindowManagerImpl.ADD_OKAY; + res = WindowManagerGlobal.ADD_OKAY; origId = Binder.clearCallingIdentity(); @@ -2313,10 +2313,10 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.getContentInsetHintLw(attrs, outContentInsets); if (mInTouchMode) { - res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE; + res |= WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE; } if (win.mAppToken == null || !win.mAppToken.clientHidden) { - res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE; + res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE; } mInputMonitor.setUpdateInputWindowsNeededLw(); @@ -2748,7 +2748,7 @@ public class WindowManagerService extends IWindowManager.Stub } winAnimator.mSurfaceDestroyDeferred = - (flags&WindowManagerImpl.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; + (flags&WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY) != 0; int attrChanges = 0; int flagChanges = 0; @@ -2967,7 +2967,7 @@ public class WindowManagerService extends IWindowManager.Stub } mLayoutNeeded = true; - win.mGivenInsetsPending = (flags&WindowManagerImpl.RELAYOUT_INSETS_PENDING) != 0; + win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0; if (assignLayers) { assignLayersLocked(win.getWindowList()); } @@ -3010,10 +3010,10 @@ public class WindowManagerService extends IWindowManager.Stub Binder.restoreCallingIdentity(origId); - return (inTouchMode ? WindowManagerImpl.RELAYOUT_RES_IN_TOUCH_MODE : 0) - | (toBeDisplayed ? WindowManagerImpl.RELAYOUT_RES_FIRST_TIME : 0) - | (surfaceChanged ? WindowManagerImpl.RELAYOUT_RES_SURFACE_CHANGED : 0) - | (animating ? WindowManagerImpl.RELAYOUT_RES_ANIMATING : 0); + return (inTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0) + | (toBeDisplayed ? WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME : 0) + | (surfaceChanged ? WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED : 0) + | (animating ? WindowManagerGlobal.RELAYOUT_RES_ANIMATING : 0); } public void performDeferredDestroyWindow(Session session, IWindow client) { @@ -5257,14 +5257,14 @@ public class WindowManagerService extends IWindowManager.Stub // Called by window manager policy. Not exposed externally. @Override - public void shutdown() { - ShutdownThread.shutdown(mContext, true); + public void shutdown(boolean confirm) { + ShutdownThread.shutdown(mContext, confirm); } // Called by window manager policy. Not exposed externally. @Override - public void rebootSafeMode() { - ShutdownThread.rebootSafeMode(mContext, true); + public void rebootSafeMode(boolean confirm) { + ShutdownThread.rebootSafeMode(mContext, confirm); } public void setInputFilter(IInputFilter filter) { @@ -8367,15 +8367,23 @@ public class WindowManagerService extends IWindowManager.Stub NN = mOpeningApps.size(); for (i=0; i<NN; i++) { AppWindowToken wtoken = mOpeningApps.get(i); + final AppWindowAnimator appAnimator = wtoken.mAppAnimator; if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken); - wtoken.mAppAnimator.clearThumbnail(); + appAnimator.clearThumbnail(); wtoken.reportedVisible = false; wtoken.inPendingTransaction = false; - wtoken.mAppAnimator.animation = null; + appAnimator.animation = null; setTokenVisibilityLocked(wtoken, animLp, true, transit, false); wtoken.updateReportedVisibilityLocked(); wtoken.waitingToShow = false; - mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked(); + + appAnimator.mAllAppWinAnimators.clear(); + final int N = wtoken.allAppWindows.size(); + for (int j = 0; j < N; j++) { + appAnimator.mAllAppWinAnimators.add(wtoken.allAppWindows.get(j).mWinAnimator); + } + mAnimator.mAnimating |= appAnimator.showAllWindowsLocked(); + if (animLp != null) { int layer = -1; for (int j=0; j<wtoken.windows.size(); j++) { @@ -9629,7 +9637,7 @@ public class WindowManagerService extends IWindowManager.Stub // TODO(multidisplay): rotation on main screen only. DisplayInfo displayInfo = getDefaultDisplayContent().getDisplayInfo(); - mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, + mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext, mDisplay, mFxSession, inTransaction, displayInfo.logicalWidth, displayInfo.logicalHeight, mDisplay.getRotation()); } @@ -9742,7 +9750,7 @@ public class WindowManagerService extends IWindowManager.Stub if (line != null) { String[] toks = line.split("%"); if (toks != null && toks.length > 0) { - mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); + mWatermark = new Watermark(mDisplay, mRealDisplayMetrics, mFxSession, toks); } } } catch (FileNotFoundException e) { diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index d931426..899610f 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -474,24 +474,14 @@ class WindowStateAnimator { private final Point mSize = new Point(); private final Rect mWindowCrop = new Rect(); private boolean mShown = false; - private int mDisplayId; - private String mName = "Not named"; + private int mLayerStack; + private String mName; public SurfaceTrace(SurfaceSession s, - int pid, int displayId, int w, int h, int format, int flags) throws - OutOfResourcesException { - super(s, pid, displayId, w, h, format, flags); - mSize.set(w, h); - mDisplayId = displayId; - Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by " - + Debug.getCallers(3)); - } - - public SurfaceTrace(SurfaceSession s, - int pid, String name, int displayId, int w, int h, int format, int flags) + int pid, String name, int layerStack, int w, int h, int format, int flags) throws OutOfResourcesException { - super(s, pid, name, displayId, w, h, format, flags); - mName = name; + super(s, pid, name, layerStack, w, h, format, flags); + mName = name != null ? name : "Not named"; mSize.set(w, h); Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by " + Debug.getCallers(3)); @@ -550,10 +540,10 @@ class WindowStateAnimator { } @Override - public void setDisplayId(int displayId) { - super.setDisplayId(displayId); - mDisplayId = displayId; - Slog.v(SURFACE_TAG, "setDisplayId: " + this + ". Called by " + Debug.getCallers(3)); + public void setLayerStack(int layerStack) { + super.setLayerStack(layerStack); + mLayerStack = layerStack; + Slog.v(SURFACE_TAG, "setLayerStack: " + this + ". Called by " + Debug.getCallers(3)); } @Override @@ -597,7 +587,7 @@ class WindowStateAnimator { @Override public String toString() { return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " " - + mName + " (" + mDisplayId + "): shown=" + mShown + " layer=" + mLayer + + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y + " " + mSize.x + "x" + mSize.y + " crop=" + mWindowCrop.toShortString(); diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp index ca6f206..8ebc6ea 100644 --- a/services/jni/com_android_server_BatteryService.cpp +++ b/services/jni/com_android_server_BatteryService.cpp @@ -42,6 +42,7 @@ struct FieldIds { // members jfieldID mAcOnline; jfieldID mUsbOnline; + jfieldID mWirelessOnline; jfieldID mBatteryStatus; jfieldID mBatteryHealth; jfieldID mBatteryPresent; @@ -71,6 +72,7 @@ static BatteryManagerConstants gConstants; struct PowerSupplyPaths { char* acOnlinePath; char* usbOnlinePath; + char* wirelessOnlinePath; char* batteryStatusPath; char* batteryHealthPath; char* batteryPresentPath; @@ -198,6 +200,7 @@ static void android_server_BatteryService_update(JNIEnv* env, jobject obj) { setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline); setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline); + setBooleanField(env, obj, gPaths.wirelessOnlinePath, gFieldIds.mWirelessOnline); setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent); setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel); @@ -260,6 +263,11 @@ int register_android_server_BatteryService(JNIEnv* env) if (access(path, R_OK) == 0) gPaths.usbOnlinePath = strdup(path); } + else if (strcmp(buf, "Wireless") == 0) { + snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name); + if (access(path, R_OK) == 0) + gPaths.wirelessOnlinePath = strdup(path); + } else if (strcmp(buf, "Battery") == 0) { snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name); if (access(path, R_OK) == 0) @@ -307,6 +315,8 @@ int register_android_server_BatteryService(JNIEnv* env) ALOGE("acOnlinePath not found"); if (!gPaths.usbOnlinePath) ALOGE("usbOnlinePath not found"); + if (!gPaths.wirelessOnlinePath) + ALOGE("wirelessOnlinePath not found"); if (!gPaths.batteryStatusPath) ALOGE("batteryStatusPath not found"); if (!gPaths.batteryHealthPath) @@ -331,6 +341,7 @@ int register_android_server_BatteryService(JNIEnv* env) gFieldIds.mAcOnline = env->GetFieldID(clazz, "mAcOnline", "Z"); gFieldIds.mUsbOnline = env->GetFieldID(clazz, "mUsbOnline", "Z"); + gFieldIds.mWirelessOnline = env->GetFieldID(clazz, "mWirelessOnline", "Z"); gFieldIds.mBatteryStatus = env->GetFieldID(clazz, "mBatteryStatus", "I"); gFieldIds.mBatteryHealth = env->GetFieldID(clazz, "mBatteryHealth", "I"); gFieldIds.mBatteryPresent = env->GetFieldID(clazz, "mBatteryPresent", "Z"); @@ -341,6 +352,7 @@ int register_android_server_BatteryService(JNIEnv* env) LOG_FATAL_IF(gFieldIds.mAcOnline == NULL, "Unable to find BatteryService.AC_ONLINE_PATH"); LOG_FATAL_IF(gFieldIds.mUsbOnline == NULL, "Unable to find BatteryService.USB_ONLINE_PATH"); + LOG_FATAL_IF(gFieldIds.mWirelessOnline == NULL, "Unable to find BatteryService.WIRELESS_ONLINE_PATH"); LOG_FATAL_IF(gFieldIds.mBatteryStatus == NULL, "Unable to find BatteryService.BATTERY_STATUS_PATH"); LOG_FATAL_IF(gFieldIds.mBatteryHealth == NULL, "Unable to find BatteryService.BATTERY_HEALTH_PATH"); LOG_FATAL_IF(gFieldIds.mBatteryPresent == NULL, "Unable to find BatteryService.BATTERY_PRESENT_PATH"); diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp index 701b15a..495d4ab 100644 --- a/services/jni/com_android_server_input_InputManagerService.cpp +++ b/services/jni/com_android_server_input_InputManagerService.cpp @@ -63,7 +63,7 @@ static const float POINTER_SPEED_EXPONENT = 1.0f / 4; static struct { jmethodID notifyConfigurationChanged; jmethodID notifyInputDevicesChanged; - jmethodID notifyLidSwitchChanged; + jmethodID notifySwitch; jmethodID notifyInputChannelBroken; jmethodID notifyANR; jmethodID filterInputEvent; @@ -578,14 +578,9 @@ void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode, JNIEnv* env = jniEnv(); - switch (switchCode) { - case SW_LID: - // When switch value is set indicates lid is closed. - env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged, - when, switchValue == 0 /*lidOpen*/); - checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged"); - break; - } + env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch, + when, switchCode, switchValue); + checkAndClearExceptionFromCallback(env, "notifySwitch"); } void NativeInputManager::notifyConfigurationChanged(nsecs_t when) { @@ -1410,8 +1405,8 @@ int register_android_server_InputManager(JNIEnv* env) { GET_METHOD_ID(gServiceClassInfo.notifyInputDevicesChanged, clazz, "notifyInputDevicesChanged", "([Landroid/view/InputDevice;)V"); - GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz, - "notifyLidSwitchChanged", "(JZ)V"); + GET_METHOD_ID(gServiceClassInfo.notifySwitch, clazz, + "notifySwitch", "(JII)V"); GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz, "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V"); |