diff options
Diffstat (limited to 'services/java/com')
9 files changed, 391 insertions, 153 deletions
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 0147b1a..6636fb7 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -49,6 +49,7 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; +import android.inputmethodservice.InputMethodService; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -59,6 +60,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; @@ -311,6 +313,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ boolean mScreenOn = true; + int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; + int mImeWindowVis; + long mOldSystemSettingsVersion; + AlertDialog.Builder mDialogBuilder; AlertDialog mSwitchingDialog; InputMethodInfo[] mIms; @@ -430,7 +436,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Uh oh, current input method is no longer around! // Pick another one... Slog.i(TAG, "Current input method removed: " + curInputMethodId); - mStatusBar.setIMEButtonVisible(mCurToken, false); + mImeWindowVis = 0; + mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, + mBackDisposition); if (!chooseNewDefaultIMELocked()) { changed = true; curIm = null; @@ -480,6 +488,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub handleMessage(msg); } }); + // Initialize the system settings version to undefined. + mOldSystemSettingsVersion = -1; (new MyPackageMonitor()).register(mContext, true); @@ -982,24 +992,34 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - public void setIMEButtonVisible(IBinder token, boolean visible) { + public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { int uid = Binder.getCallingUid(); long ident = Binder.clearCallingIdentity(); try { if (token == null || mCurToken != token) { - Slog.w(TAG, "Ignoring setIMEButtonVisible of uid " + uid + " token: " + token); + Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token); return; } synchronized (mMethodMap) { - mStatusBar.setIMEButtonVisible(token, visible); + mImeWindowVis = vis; + mBackDisposition = backDisposition; + mStatusBar.setImeWindowStatus(token, vis, backDisposition); } } finally { Binder.restoreCallingIdentity(ident); } } + // TODO: Investigate and fix why are settings changes getting processed before the settings seq + // number is updated? + // TODO: Change this stuff to not rely on modifying settings for normal user interactions. void updateFromSettingsLocked() { + long newSystemSettingsVersion = getSystemSettingsVersion(); + // This is a workaround to avoid a situation that old cached value in Settings.Secure + // will be handled. + if (newSystemSettingsVersion == mOldSystemSettingsVersion) return; + // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and // ENABLED_INPUT_METHODS is taking care of keeping them correctly in // sync, so we will never have a DEFAULT_INPUT_METHOD that is not @@ -1045,12 +1065,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (mCurMethod != null) { try { - if (mInputShown) { - // If mInputShown is false, there is no IME button on the - // system bar. - // Thus there is no need to make it invisible explicitly. - mStatusBar.setIMEButtonVisible(mCurToken, true); - } + final Configuration conf = mRes.getConfiguration(); + final boolean haveHardKeyboard = conf.keyboard + != Configuration.KEYBOARD_NOKEYS; + final boolean hardKeyShown = haveHardKeyboard + && conf.hardKeyboardHidden + != Configuration.HARDKEYBOARDHIDDEN_YES; + mImeWindowVis = (mInputShown || hardKeyShown) ? ( + InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) + : 0; + mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, + mBackDisposition); // If subtype is null, try to find the most applicable one from // getCurrentInputMethodSubtype. if (subtype == null) { @@ -1168,11 +1193,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!mIWindowManager.inputMethodClientHasFocus(client)) { if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client); - mStatusBar.setIMEButtonVisible(mCurToken, false); + mImeWindowVis = 0; + mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, + mBackDisposition); return false; } } catch (RemoteException e) { - mStatusBar.setIMEButtonVisible(mCurToken, false); + mImeWindowVis = 0; + mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition); return false; } } @@ -1942,6 +1970,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId, boolean setSubtypeOnly) { + mOldSystemSettingsVersion = getSystemSettingsVersion(); // Update the history of InputMethod and Subtype saveCurrentInputMethodAndSubtypeToHistory(); @@ -2191,6 +2220,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + private static long getSystemSettingsVersion() { + return SystemProperties.getLong(Settings.Secure.SYS_PROP_SETTING_VERSION, 0); + } + /** * @return Return the current subtype of this input method. */ diff --git a/services/java/com/android/server/IntentResolver.java b/services/java/com/android/server/IntentResolver.java index a8b2840..e9ee12c 100644 --- a/services/java/com/android/server/IntentResolver.java +++ b/services/java/com/android/server/IntentResolver.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import android.net.Uri; +import android.util.FastImmutableArraySet; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Slog; @@ -207,10 +209,11 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { final boolean debug = localLOGV || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); + FastImmutableArraySet<String> categories = getFastIntentCategories(intent); final String scheme = intent.getScheme(); int N = listCut.size(); for (int i = 0; i < N; ++i) { - buildResolveList(intent, debug, defaultOnly, + buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, listCut.get(i), resultList); } sortResults(resultList); @@ -286,20 +289,21 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { if (debug) Slog.v(TAG, "Action list: " + firstTypeCut); } + FastImmutableArraySet<String> categories = getFastIntentCategories(intent); if (firstTypeCut != null) { - buildResolveList(intent, debug, defaultOnly, + buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, firstTypeCut, finalList); } if (secondTypeCut != null) { - buildResolveList(intent, debug, defaultOnly, + buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, secondTypeCut, finalList); } if (thirdTypeCut != null) { - buildResolveList(intent, debug, defaultOnly, + buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, thirdTypeCut, finalList); } if (schemeCut != null) { - buildResolveList(intent, debug, defaultOnly, + buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, schemeCut, finalList); } sortResults(finalList); @@ -478,9 +482,19 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { return false; } - private void buildResolveList(Intent intent, boolean debug, boolean defaultOnly, + private static FastImmutableArraySet<String> getFastIntentCategories(Intent intent) { + final Set<String> categories = intent.getCategories(); + if (categories == null) { + return null; + } + return new FastImmutableArraySet<String>(categories.toArray(new String[categories.size()])); + } + + private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories, + boolean debug, boolean defaultOnly, String resolvedType, String scheme, List<F> src, List<R> dest) { - Set<String> categories = intent.getCategories(); + final String action = intent.getAction(); + final Uri data = intent.getData(); final int N = src != null ? src.size() : 0; boolean hasNonDefaults = false; @@ -498,8 +512,7 @@ public class IntentResolver<F extends IntentFilter, R extends Object> { continue; } - match = filter.match( - intent.getAction(), resolvedType, scheme, intent.getData(), categories, TAG); + match = filter.match(action, resolvedType, scheme, data, categories, TAG); if (match >= 0) { if (debug) Slog.v(TAG, " Filter matched! match=0x" + Integer.toHexString(match)); diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index 3101222..436eff0 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -46,6 +46,7 @@ import android.os.storage.IMountShutdownObserver; import android.os.storage.IObbActionListener; import android.os.storage.OnObbStateChangeListener; import android.os.storage.StorageResultCode; +import android.text.TextUtils; import android.util.Slog; import java.io.FileDescriptor; @@ -1632,8 +1633,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC } public int decryptStorage(String password) { - if (password == null) { - throw new IllegalArgumentException("password cannot be null"); + if (TextUtils.isEmpty(password)) { + throw new IllegalArgumentException("password cannot be empty"); } mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, @@ -1647,13 +1648,13 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC try { ArrayList<String> rsp = mConnector.doCommand("cryptfs checkpw " + password); - String []tok = rsp.get(0).split(" "); + String[] tokens = rsp.get(0).split(" "); - if (tok == null || tok.length != 2) { + if (tokens == null || tokens.length != 2) { return -1; } - int code = Integer.parseInt(tok[1]); + int code = Integer.parseInt(tokens[1]); if (code == 0) { // Decrypt was successful. Post a delayed message before restarting in order @@ -1662,7 +1663,7 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC public void run() { mConnector.doCommand(String.format("cryptfs restart")); } - }, 2000); // 2 seconds + }, 1000); // 1 second } return code; @@ -1673,8 +1674,8 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC } public int encryptStorage(String password) { - if (password == null) { - throw new IllegalArgumentException("password cannot be null"); + if (TextUtils.isEmpty(password)) { + throw new IllegalArgumentException("password cannot be empty"); } mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, @@ -1696,6 +1697,36 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC return 0; } + public int changeEncryptionPassword(String password) { + if (TextUtils.isEmpty(password)) { + throw new IllegalArgumentException("password cannot be empty"); + } + + mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER, + "no permission to access the crypt keeper"); + + waitForReady(); + + if (DEBUG_EVENTS) { + Slog.i(TAG, "changing encryption password..."); + } + + try { + ArrayList<String> response = mConnector.doCommand("cryptfs changepw " + password); + + String[] tokens = response.get(0).split(" "); + + if (tokens == null || tokens.length != 2) { + return -1; + } + + return Integer.parseInt(tokens[1]); + } catch (NativeDaemonConnectorException e) { + // Encryption failed + return e.getCode(); + } + } + private void addObbStateLocked(ObbState obbState) throws RemoteException { final IBinder binder = obbState.getBinder(); List<ObbState> obbStates = mObbMounts.get(binder); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 5806de2..9ee71e8 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -2924,26 +2924,6 @@ class PackageManagerService extends IPackageManager.Stub { } } - if (pkg.reqFeatures != null) { - int N = pkg.reqFeatures.size(); - for (int i = 0; i < N; i++) { - FeatureInfo fi = pkg.reqFeatures.get(i); - if ((fi.flags & FeatureInfo.FLAG_REQUIRED) == 0) { - // Don't care. - continue; - } - - if (fi.name != null) { - if (mAvailableFeatures.get(fi.name) == null) { - Slog.e(TAG, "Package " + pkg.packageName - + " requires unavailable feature " + fi.name + "; failing!"); - mLastScanError = PackageManager.INSTALL_FAILED_MISSING_FEATURE; - return null; - } - } - } - } - if (pkg.mSharedUserId != null) { suid = mSettings.getSharedUserLP(pkg.mSharedUserId, pkg.applicationInfo.flags, true); diff --git a/services/java/com/android/server/StatusBarManagerService.java b/services/java/com/android/server/StatusBarManagerService.java index bdaa3b0..5ada77b 100644 --- a/services/java/com/android/server/StatusBarManagerService.java +++ b/services/java/com/android/server/StatusBarManagerService.java @@ -53,11 +53,13 @@ import java.util.Map; * if they are local, that they just enqueue messages to not deadlock. */ public class StatusBarManagerService extends IStatusBarService.Stub + implements WindowManagerService.OnHardKeyboardStatusChangeListener { static final String TAG = "StatusBarManagerService"; static final boolean SPEW = false; final Context mContext; + final WindowManagerService mWindowManager; Handler mHandler = new Handler(); NotificationCallbacks mNotificationCallbacks; volatile IStatusBar mBar; @@ -67,14 +69,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub // for disabling the status bar ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>(); + IBinder mSysUiVisToken = new Binder(); int mDisabled = 0; Object mLock = new Object(); // We usually call it lights out mode, but double negatives are annoying boolean mLightsOn = true; boolean mMenuVisible = false; - boolean mIMEButtonVisible = false; - IBinder mIMEToken = null; + int mImeWindowVis = 0; + int mImeBackDisposition; + IBinder mImeToken = null; private class DisableRecord implements IBinder.DeathRecipient { String pkg; @@ -101,8 +105,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub /** * Construct the service, add the status bar view to the window manager */ - public StatusBarManagerService(Context context) { + public StatusBarManagerService(Context context, WindowManagerService windowManager) { mContext = context; + mWindowManager = windowManager; + mWindowManager.setOnHardKeyboardStatusChangeListener(this); final Resources res = context.getResources(); mIcons.defineSlots(res.getStringArray(com.android.internal.R.array.config_statusBarIcons)); @@ -140,25 +146,29 @@ public class StatusBarManagerService extends IStatusBarService.Stub public void disable(int what, IBinder token, String pkg) { enforceStatusBar(); + synchronized (mLock) { + disableLocked(what, token, pkg); + } + } + + private void disableLocked(int what, IBinder token, String pkg) { // It's important that the the callback and the call to mBar get done // in the same order when multiple threads are calling this function // so they are paired correctly. The messages on the handler will be // handled in the order they were enqueued, but will be outside the lock. - synchronized (mDisableRecords) { - manageDisableListLocked(what, token, pkg); - final int net = gatherDisableActionsLocked(); - if (net != mDisabled) { - mDisabled = net; - mHandler.post(new Runnable() { - public void run() { - mNotificationCallbacks.onSetDisabled(net); - } - }); - if (mBar != null) { - try { - mBar.disable(net); - } catch (RemoteException ex) { + manageDisableListLocked(what, token, pkg); + final int net = gatherDisableActionsLocked(); + if (net != mDisabled) { + mDisabled = net; + mHandler.post(new Runnable() { + public void run() { + mNotificationCallbacks.onSetDisabled(net); } + }); + if (mBar != null) { + try { + mBar.disable(net); + } catch (RemoteException ex) { } } } @@ -259,22 +269,25 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } - public void setIMEButtonVisible(final IBinder token, final boolean visible) { + public void setImeWindowStatus(final IBinder token, final int vis, final int backDisposition) { enforceStatusBar(); - if (SPEW) Slog.d(TAG, (visible?"showing":"hiding") + " IME Button"); + if (SPEW) { + Slog.d(TAG, "swetImeWindowStatus vis=" + vis + " backDisposition=" + backDisposition); + } synchronized(mLock) { - // In case of IME change, we need to call up setIMEButtonVisible() regardless of - // mIMEButtonVisible because mIMEButtonVisible may not have been set to false when the + // In case of IME change, we need to call up setImeWindowStatus() regardless of + // mImeWindowVis because mImeWindowVis may not have been set to false when the // previous IME was destroyed. - mIMEButtonVisible = visible; - mIMEToken = token; + mImeWindowVis = vis; + mImeBackDisposition = backDisposition; + mImeToken = token; mHandler.post(new Runnable() { public void run() { if (mBar != null) { try { - mBar.setIMEButtonVisible(token, visible); + mBar.setImeWindowStatus(token, vis, backDisposition); } catch (RemoteException ex) { } } @@ -290,6 +303,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub synchronized (mLock) { final boolean lightsOn = (vis & View.STATUS_BAR_HIDDEN) == 0; updateLightsOnLocked(lightsOn); + disableLocked(vis & StatusBarManager.DISABLE_MASK, mSysUiVisToken, + "WindowManager.LayoutParams"); } } @@ -309,6 +324,28 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } + public void setHardKeyboardEnabled(final boolean enabled) { + mHandler.post(new Runnable() { + public void run() { + mWindowManager.setHardKeyboardEnabled(enabled); + } + }); + } + + @Override + public void onHardKeyboardStatusChange(final boolean available, final boolean enabled) { + mHandler.post(new Runnable() { + public void run() { + if (mBar != null) { + try { + mBar.setHardKeyboardStatus(available, enabled); + } catch (RemoteException ex) { + } + } + } + }); + } + private void enforceStatusBar() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR, "StatusBarManagerService"); @@ -324,7 +361,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub "StatusBarManagerService"); } - // ================================================================================ // Callbacks from the status bar service. // ================================================================================ @@ -348,9 +384,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub switches[0] = gatherDisableActionsLocked(); switches[1] = mLightsOn ? 1 : 0; switches[2] = mMenuVisible ? 1 : 0; - switches[3] = mIMEButtonVisible ? 1 : 0; - binders.add(mIMEToken); + switches[3] = mImeWindowVis; + switches[4] = mImeBackDisposition; + binders.add(mImeToken); } + switches[5] = mWindowManager.isHardKeyboardAvailable() ? 1 : 0; + switches[6] = mWindowManager.isHardKeyboardEnabled() ? 1 : 0; } /** @@ -447,37 +486,35 @@ public class StatusBarManagerService extends IStatusBarService.Stub Slog.d(TAG, "manageDisableList what=0x" + Integer.toHexString(what) + " pkg=" + pkg); } // update the list - synchronized (mDisableRecords) { - final int N = mDisableRecords.size(); - DisableRecord tok = null; - int i; - for (i=0; i<N; i++) { - DisableRecord t = mDisableRecords.get(i); - if (t.token == token) { - tok = t; - break; - } + final int N = mDisableRecords.size(); + DisableRecord tok = null; + int i; + for (i=0; i<N; i++) { + DisableRecord t = mDisableRecords.get(i); + if (t.token == token) { + tok = t; + break; + } + } + if (what == 0 || !token.isBinderAlive()) { + if (tok != null) { + mDisableRecords.remove(i); + tok.token.unlinkToDeath(tok, 0); } - if (what == 0 || !token.isBinderAlive()) { - if (tok != null) { - mDisableRecords.remove(i); - tok.token.unlinkToDeath(tok, 0); + } else { + if (tok == null) { + tok = new DisableRecord(); + try { + token.linkToDeath(tok, 0); } - } else { - if (tok == null) { - tok = new DisableRecord(); - try { - token.linkToDeath(tok, 0); - } - catch (RemoteException ex) { - return; // give up - } - mDisableRecords.add(tok); + catch (RemoteException ex) { + return; // give up } - tok.what = what; - tok.token = token; - tok.pkg = pkg; + mDisableRecords.add(tok); } + tok.what = what; + tok.token = token; + tok.pkg = pkg; } } @@ -518,7 +555,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub } } - synchronized (mDisableRecords) { + synchronized (mLock) { final int N = mDisableRecords.size(); pw.println(" mDisableRecords.size=" + N + " mDisabled=0x" + Integer.toHexString(mDisabled)); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 62ff064..683c2c0 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -248,7 +248,7 @@ class ServerThread extends Thread { try { Slog.i(TAG, "Status Bar"); - statusBar = new StatusBarManagerService(context); + statusBar = new StatusBarManagerService(context, wm); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } catch (Throwable e) { Slog.e(TAG, "Failure starting StatusBarManagerService", e); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 04f4e4e..5e78353 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -890,10 +890,10 @@ public class WifiService extends IWifiManager.Stub { * @see #shouldDeviceStayAwake(int, int) */ private boolean shouldWifiStayAwake(int stayAwakeConditions, int pluggedType) { - //Never sleep when plugged in as long as the user has not changed the settings + //Never sleep as long as the user has not changed the settings int wifiSleepPolicy = Settings.System.getInt(mContext.getContentResolver(), Settings.System.WIFI_SLEEP_POLICY, - Settings.System.WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED); + Settings.System.WIFI_SLEEP_POLICY_NEVER); if (wifiSleepPolicy == Settings.System.WIFI_SLEEP_POLICY_NEVER) { // Never sleep diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 30a9432..17c3154 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -47,6 +47,7 @@ import com.android.server.am.BatteryStatsService; import android.Manifest; import android.app.ActivityManagerNative; import android.app.IActivityManager; +import android.app.StatusBarManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.ClipData; @@ -454,6 +455,10 @@ public class WindowManagerService extends IWindowManager.Stub WindowState mInputMethodWindow = null; final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>(); + boolean mHardKeyboardAvailable; + boolean mHardKeyboardEnabled; + OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener; + final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>(); // If non-null, this is the currently visible window that is associated @@ -1315,7 +1320,20 @@ public class WindowManagerService extends IWindowManager.Stub static boolean canBeImeTarget(WindowState w) { final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); - if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) { + if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) + || w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) { + if (DEBUG_INPUT_METHOD) { + Slog.i(TAG, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding()); + if (!w.isVisibleOrAdding()) { + Slog.i(TAG, " mSurface=" + w.mSurface + " reportDestroy=" + w.mReportDestroySurface + + " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility + + " policyVis=" + w.mPolicyVisibility + " attachHid=" + w.mAttachedHidden + + " exiting=" + w.mExiting + " destroying=" + w.mDestroying); + if (w.mAppToken != null) { + Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested); + } + } + } return w.isVisibleOrAdding(); } return false; @@ -1330,8 +1348,8 @@ public class WindowManagerService extends IWindowManager.Stub i--; w = localmWindows.get(i); - //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x" - // + Integer.toHexString(w.mAttrs.flags)); + if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG, "Checking window @" + i + + " " + w + " fl=0x" + Integer.toHexString(w.mAttrs.flags)); if (canBeImeTarget(w)) { //Slog.i(TAG, "Putting input method here!"); @@ -1353,6 +1371,8 @@ public class WindowManagerService extends IWindowManager.Stub } } + if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG, "Proposed new IME target: " + w); + // Now, a special case -- if the last target's window is in the // process of exiting, and is above the new target, keep on the // last target to avoid flicker. Consider for example a Dialog with @@ -1365,6 +1385,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mInputMethodTarget.mAnimLayer > w.mAnimLayer) { w = mInputMethodTarget; i = localmWindows.indexOf(w); + if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Current target higher, switching to: " + w); } } @@ -1420,6 +1441,7 @@ public class WindowManagerService extends IWindowManager.Stub // with an animation, and it is on top of the next target // we will be over, then hold off on moving until // that is done. + mInputMethodTargetWaitingAnim = true; mInputMethodTarget = highestTarget; return highestPos + 1; } @@ -1440,6 +1462,7 @@ public class WindowManagerService extends IWindowManager.Stub + mInputMethodTarget + " to " + w, e); } mInputMethodTarget = w; + mInputMethodTargetWaitingAnim = false; if (w.mAppToken != null) { setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment); } else { @@ -2736,6 +2759,15 @@ public class WindowManagerService extends IWindowManager.Stub boolean displayed = false; boolean inTouchMode; boolean configChanged; + + // if they don't have this permission, mask out the status bar bits + if (attrs != null) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + != PackageManager.PERMISSION_GRANTED) { + attrs.systemUiVisibility &= ~StatusBarManager.DISABLE_MASK; + attrs.subtreeSystemUiVisibility &= ~StatusBarManager.DISABLE_MASK; + } + } long origId = Binder.clearCallingIdentity(); synchronized(mWindowMap) { @@ -5735,13 +5767,13 @@ public class WindowManagerService extends IWindowManager.Stub mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; } else { mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL; - - // If this screen is wider than normal HVGA, or taller - // than FWVGA, then for old apps we want to run in size - // compatibility mode. - if (shortSize > 321 || longSize > 570) { - mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; - } + } + + // If this screen is wider than normal HVGA, or taller + // than FWVGA, then for old apps we want to run in size + // compatibility mode. + if (shortSize > 321 || longSize > 570) { + mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; } // Is this a long screen? @@ -5755,12 +5787,70 @@ public class WindowManagerService extends IWindowManager.Stub } config.screenLayout = mScreenLayout; + // Determine whether a hard keyboard is available and enabled. + boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS; + if (hardKeyboardAvailable != mHardKeyboardAvailable) { + mHardKeyboardAvailable = hardKeyboardAvailable; + mHardKeyboardEnabled = hardKeyboardAvailable; + + mH.removeMessages(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); + mH.sendEmptyMessage(H.REPORT_HARD_KEYBOARD_STATUS_CHANGE); + } + if (!mHardKeyboardEnabled) { + config.keyboard = Configuration.KEYBOARD_NOKEYS; + } + + // Update value of keyboardHidden, hardKeyboardHidden and navigationHidden + // based on whether a hard or soft keyboard is present, whether navigation keys + // are present and the lid switch state. config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; + config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO; mPolicy.adjustConfigurationLw(config); return true; } + public boolean isHardKeyboardAvailable() { + synchronized (mWindowMap) { + return mHardKeyboardAvailable; + } + } + + public boolean isHardKeyboardEnabled() { + synchronized (mWindowMap) { + return mHardKeyboardEnabled; + } + } + + public void setHardKeyboardEnabled(boolean enabled) { + synchronized (mWindowMap) { + if (mHardKeyboardEnabled != enabled) { + mHardKeyboardEnabled = enabled; + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); + } + } + } + + public void setOnHardKeyboardStatusChangeListener( + OnHardKeyboardStatusChangeListener listener) { + synchronized (mWindowMap) { + mHardKeyboardStatusChangeListener = listener; + } + } + + void notifyHardKeyboardStatusChange() { + final boolean available, enabled; + final OnHardKeyboardStatusChangeListener listener; + synchronized (mWindowMap) { + listener = mHardKeyboardStatusChangeListener; + available = mHardKeyboardAvailable; + enabled = mHardKeyboardEnabled; + } + if (listener != null) { + listener.onHardKeyboardStatusChange(available, enabled); + } + } + // ------------------------------------------------------------- // Drag and drop // ------------------------------------------------------------- @@ -5786,8 +5876,7 @@ public class WindowManagerService extends IWindowManager.Stub outSurface.copyFrom(surface); final IBinder winBinder = window.asBinder(); token = new Binder(); - // TODO: preserve flags param in DragState - mDragState = new DragState(token, surface, 0, winBinder); + mDragState = new DragState(token, surface, flags, winBinder); mDragState.mSurface = surface; token = mDragState.mToken = new Binder(); @@ -8539,7 +8628,7 @@ public class WindowManagerService extends IWindowManager.Stub w.mAnimLayer = w.mLayer + adj; if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": " + w.mAnimLayer); - if (w == mInputMethodTarget) { + if (w == mInputMethodTarget && !mInputMethodTargetWaitingAnim) { setInputMethodAnimLayerAdjustment(adj); } if (w == mWallpaperTarget && mLowerWallpaperTarget == null) { @@ -8630,6 +8719,10 @@ public class WindowManagerService extends IWindowManager.Stub clearAnimation(); animating = false; + if (animLayerAdjustment != 0) { + animLayerAdjustment = 0; + updateLayers(); + } if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) { moveInputMethodWindowsIfNeededLocked(true); } @@ -8639,10 +8732,6 @@ public class WindowManagerService extends IWindowManager.Stub + ": reportedVisible=" + reportedVisible); transformation.clear(); - if (animLayerAdjustment != 0) { - animLayerAdjustment = 0; - updateLayers(); - } final int N = windows.size(); for (int i=0; i<N; i++) { @@ -8851,6 +8940,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int REPORT_WINDOWS_CHANGE = 19; public static final int DRAG_START_TIMEOUT = 20; public static final int DRAG_END_TIMEOUT = 21; + public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; private Session mLastReportedHold; @@ -9224,6 +9314,11 @@ public class WindowManagerService extends IWindowManager.Stub } break; } + + case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { + notifyHardKeyboardStatusChange(); + break; + } } } } @@ -9248,11 +9343,47 @@ public class WindowManagerService extends IWindowManager.Stub WindowState imFocus; if (idx > 0) { imFocus = mWindows.get(idx-1); + //Log.i(TAG, "Desired input method target: " + imFocus); + //Log.i(TAG, "Current focus: " + this.mCurrentFocus); + //Log.i(TAG, "Last focus: " + this.mLastFocus); if (imFocus != null) { + // This may be a starting window, in which case we still want + // to count it as okay. + if (imFocus.mAttrs.type == LayoutParams.TYPE_APPLICATION_STARTING + && imFocus.mAppToken != null) { + // The client has definitely started, so it really should + // have a window in this app token. Let's look for it. + for (int i=0; i<imFocus.mAppToken.windows.size(); i++) { + WindowState w = imFocus.mAppToken.windows.get(i); + if (w != imFocus) { + //Log.i(TAG, "Switching to real app window: " + w); + imFocus = w; + break; + } + } + } + //Log.i(TAG, "IM target client: " + imFocus.mSession.mClient); + //if (imFocus.mSession.mClient != null) { + // Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder()); + // Log.i(TAG, "Requesting client binder: " + client.asBinder()); + //} if (imFocus.mSession.mClient != null && imFocus.mSession.mClient.asBinder() == client.asBinder()) { return true; } + + // Okay, how about this... what is the current focus? + // It seems in some cases we may not have moved the IM + // target window, such as when it was in a pop-up window, + // so let's also look at the current focus. (An example: + // go to Gmail, start searching so the keyboard goes up, + // press home. Sometimes the IME won't go down.) + // Would be nice to fix this more correctly, but it's + // way at the end of a release, and this should be good enough. + if (mCurrentFocus != null && mCurrentFocus.mSession.mClient != null && + mCurrentFocus.mSession.mClient.asBinder() == client.asBinder()) { + return true; + } } } } @@ -11261,13 +11392,13 @@ public class WindowManagerService extends IWindowManager.Stub mInputMonitor.thawInputDispatchingLw(); + boolean configChanged; + // While the display is frozen we don't re-compute the orientation // to avoid inconsistent states. However, something interesting // could have actually changed during that time so re-evaluate it // now to catch that. - if (updateOrientationFromAppTokensLocked(false)) { - mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); - } + configChanged = updateOrientationFromAppTokensLocked(false); // A little kludge: a lot could have happened while the // display was frozen, so now that we are coming back we @@ -11282,11 +11413,12 @@ public class WindowManagerService extends IWindowManager.Stub if (updateRotation) { if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation"); - boolean changed = setRotationUncheckedLocked( + configChanged |= setRotationUncheckedLocked( WindowManagerPolicy.USE_LAST_ROTATION, 0, false); - if (changed) { - sendNewConfiguration(); - } + } + + if (configChanged) { + mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } } @@ -11933,4 +12065,8 @@ public class WindowManagerService extends IWindowManager.Stub return Animation.ZORDER_TOP; } } + + public interface OnHardKeyboardStatusChangeListener { + public void onHardKeyboardStatusChange(boolean available, boolean enabled); + } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index da70f61..9e3b9c6 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -11947,28 +11947,6 @@ public final class ActivityManagerService extends ActivityManagerNative adj = FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "exec-service"; - } else if (app.foregroundServices) { - // The user is aware of this app, so make it visible. - adj = PERCEPTIBLE_APP_ADJ; - schedGroup = Process.THREAD_GROUP_DEFAULT; - app.adjType = "foreground-service"; - } else if (app.forcingToForeground != null) { - // The user is aware of this app, so make it visible. - adj = PERCEPTIBLE_APP_ADJ; - schedGroup = Process.THREAD_GROUP_DEFAULT; - app.adjType = "force-foreground"; - app.adjSource = app.forcingToForeground; - } else if (app == mHeavyWeightProcess) { - // We don't want to kill the current heavy-weight process. - adj = HEAVY_WEIGHT_APP_ADJ; - schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; - app.adjType = "heavy"; - } else if (app == mHomeProcess) { - // This process is hosting what we currently consider to be the - // home app, so we don't want to let it go into the background. - adj = HOME_APP_ADJ; - schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; - app.adjType = "home"; } else if ((N=app.activities.size()) != 0) { // This app is in the background with paused activities. app.hidden = true; @@ -12001,7 +11979,37 @@ public final class ActivityManagerService extends ActivityManagerNative adj = hiddenAdj; app.adjType = "bg-empty"; } + + if (adj > PERCEPTIBLE_APP_ADJ) { + if (app.foregroundServices) { + // The user is aware of this app, so make it visible. + adj = PERCEPTIBLE_APP_ADJ; + schedGroup = Process.THREAD_GROUP_DEFAULT; + app.adjType = "foreground-service"; + } else if (app.forcingToForeground != null) { + // The user is aware of this app, so make it visible. + adj = PERCEPTIBLE_APP_ADJ; + schedGroup = Process.THREAD_GROUP_DEFAULT; + app.adjType = "force-foreground"; + app.adjSource = app.forcingToForeground; + } + } + + if (adj > HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) { + // We don't want to kill the current heavy-weight process. + adj = HEAVY_WEIGHT_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.adjType = "heavy"; + } + if (adj > HOME_APP_ADJ && app == mHomeProcess) { + // This process is hosting what we currently consider to be the + // home app, so we don't want to let it go into the background. + adj = HOME_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.adjType = "home"; + } + //Slog.i(TAG, "OOM " + app + ": initial adj=" + adj); // By default, we use the computed adjustment. It may be changed if |
