diff options
Diffstat (limited to 'services/java')
10 files changed, 512 insertions, 312 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 041c13b..c751f3d 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -889,7 +889,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); if (info.isFailover()) { intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); @@ -1005,7 +1004,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void sendConnectedBroadcast(NetworkInfo info) { Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); if (info.isFailover()) { intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); @@ -1043,7 +1041,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { } Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); - intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); if (getActiveNetworkInfo() == null) { intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 4d35bec..c61baad 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -77,9 +77,12 @@ import android.view.inputmethod.EditorInfo; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.text.Collator; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * This class provides a system service that manages input methods. @@ -463,14 +466,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt); + mStatusBar = statusBar; + statusBar.setIconVisibility("ime", false); + buildInputMethodListLocked(mMethodList, mMethodMap); final String enabledStr = Settings.Secure.getString( mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS); Slog.i(TAG, "Enabled input methods: " + enabledStr); - if (enabledStr == null) { - Slog.i(TAG, "Enabled input methods has not been set, enabling all"); + final String defaultIme = Settings.Secure.getString(mContext + .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); + if (enabledStr == null || TextUtils.isEmpty(defaultIme)) { + Slog.i(TAG, "Enabled input methods or default IME has not been set, enabling all"); InputMethodInfo defIm = null; StringBuilder sb = new StringBuilder(256); final int N = mMethodList.size(); @@ -504,9 +512,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - mStatusBar = statusBar; - statusBar.setIconVisibility("ime", false); - mSettingsObserver = new SettingsObserver(mHandler); updateFromSettingsLocked(); } @@ -978,7 +983,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void setInputMethodLocked(String id) { InputMethodInfo info = mMethodMap.get(id); if (info == null) { - throw new IllegalArgumentException("Unknown id: " + mCurMethodId); + throw new IllegalArgumentException("Unknown id: " + id); } if (id.equals(mCurMethodId)) { @@ -1476,7 +1481,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub String defaultIme = Settings.Secure.getString(mContext .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); - if (!map.containsKey(defaultIme)) { + if (!TextUtils.isEmpty(defaultIme) && !map.containsKey(defaultIme)) { if (chooseNewDefaultIMELocked()) { updateFromSettingsLocked(); } @@ -1506,21 +1511,22 @@ public class InputMethodManagerService extends IInputMethodManager.Stub hideInputMethodMenuLocked(); int N = immis.size(); - - mItems = new CharSequence[N]; - mIms = new InputMethodInfo[N]; - - int j = 0; + + final Map<CharSequence, InputMethodInfo> imMap = + new TreeMap<CharSequence, InputMethodInfo>(Collator.getInstance()); + for (int i = 0; i < N; ++i) { InputMethodInfo property = immis.get(i); if (property == null) { continue; } - mItems[j] = property.loadLabel(pm); - mIms[j] = property; - j++; + imMap.put(property.loadLabel(pm), property); } - + + N = imMap.size(); + mItems = imMap.keySet().toArray(new CharSequence[N]); + mIms = imMap.values().toArray(new InputMethodInfo[N]); + int checkedItem = 0; for (int i = 0; i < N; ++i) { if (mIms[i].getId().equals(lastInputMethodId)) { diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 421d1c4..9b9d950 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -4808,6 +4808,8 @@ public class WindowManagerService extends IWindowManager.Stub Parcel data = null; Parcel reply = null; + BufferedWriter out = null; + // Any uncaught exception will crash the system process try { // Find the hashcode of the window @@ -4845,6 +4847,12 @@ public class WindowManagerService extends IWindowManager.Stub reply.readException(); + if (!client.isOutputShutdown()) { + out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); + out.write("DONE\n"); + out.flush(); + } + } catch (Exception e) { Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e); success = false; @@ -4855,6 +4863,13 @@ public class WindowManagerService extends IWindowManager.Stub if (reply != null) { reply.recycle(); } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + + } + } } return success; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index b37cd89..d535343 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -609,8 +609,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen * All currently bound service connections. Keys are the IBinder of * the client's IServiceConnection. */ - final HashMap<IBinder, ConnectionRecord> mServiceConnections - = new HashMap<IBinder, ConnectionRecord>(); + final HashMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections + = new HashMap<IBinder, ArrayList<ConnectionRecord>>(); /** * List of services that we have been asked to start, @@ -4294,12 +4294,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " when granting permission to uri " + uri); } if (targetPkg == null) { - Slog.w(TAG, "grantUriPermission: null target"); - return; + throw new IllegalArgumentException("null target"); } if (uri == null) { - Slog.w(TAG, "grantUriPermission: null uri"); - return; + throw new IllegalArgumentException("null uri"); } grantUriPermissionLocked(r.info.uid, targetPkg, uri, modeFlags, @@ -4451,6 +4449,56 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + @Override + public IBinder newUriPermissionOwner(String name) { + synchronized(this) { + UriPermissionOwner owner = new UriPermissionOwner(this, name); + return owner.getExternalTokenLocked(); + } + } + + @Override + public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, + Uri uri, int modeFlags) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + if (fromUid != Binder.getCallingUid()) { + if (Binder.getCallingUid() != Process.myUid()) { + // Only system code can grant URI permissions on behalf + // of other users. + throw new SecurityException("nice try"); + } + } + if (targetPkg == null) { + throw new IllegalArgumentException("null target"); + } + if (uri == null) { + throw new IllegalArgumentException("null uri"); + } + + grantUriPermissionLocked(fromUid, targetPkg, uri, modeFlags, owner); + } + } + + @Override + public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode) { + synchronized(this) { + UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token); + if (owner == null) { + throw new IllegalArgumentException("Unknown owner: " + token); + } + + if (uri == null) { + owner.removeUriPermissionsLocked(mode); + } else { + owner.removeUriPermissionLocked(uri, mode); + } + } + } + public void showWaitingForDebugger(IApplicationThread who, boolean waiting) { synchronized (this) { ProcessRecord app = @@ -7376,12 +7424,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (mServiceConnections.size() > 0) { if (needSep) pw.println(" "); pw.println(" Connection bindings to services:"); - Iterator<ConnectionRecord> it + Iterator<ArrayList<ConnectionRecord>> it = mServiceConnections.values().iterator(); while (it.hasNext()) { - ConnectionRecord r = it.next(); - pw.print(" * "); pw.println(r); - r.dump(pw, " "); + ArrayList<ConnectionRecord> r = it.next(); + for (int i=0; i<r.size(); i++) { + pw.print(" * "); pw.println(r.get(i)); + r.get(i).dump(pw, " "); + } } needSep = true; } @@ -7659,18 +7709,21 @@ public final class ActivityManagerService extends ActivityManagerNative implemen while (it.hasNext()) { ServiceRecord r = it.next(); if (r.connections.size() > 0) { - Iterator<ConnectionRecord> jt + Iterator<ArrayList<ConnectionRecord>> jt = r.connections.values().iterator(); while (jt.hasNext()) { - ConnectionRecord c = jt.next(); - if (c.binding.client != app) { - try { - //c.conn.connected(r.className, null); - } catch (Exception e) { - // todo: this should be asynchronous! - Slog.w(TAG, "Exception thrown disconnected servce " - + r.shortName - + " from app " + app.processName, e); + ArrayList<ConnectionRecord> cl = jt.next(); + for (int i=0; i<cl.size(); i++) { + ConnectionRecord c = cl.get(i); + if (c.binding.client != app) { + try { + //c.conn.connected(r.className, null); + } catch (Exception e) { + // todo: this should be asynchronous! + Slog.w(TAG, "Exception thrown disconnected servce " + + r.shortName + + " from app " + app.processName, e); + } } } } @@ -7700,7 +7753,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } sr.app = null; sr.executeNesting = 0; - mStoppingServices.remove(sr); + if (mStoppingServices.remove(sr)) { + if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr); + } boolean hasClients = sr.bindings.size() > 0; if (hasClients) { @@ -7753,6 +7808,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen ServiceRecord sr = mStoppingServices.get(i); if (sr.app == app) { mStoppingServices.remove(i); + if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr); } } @@ -8016,11 +8072,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (r.app != null && r.app.persistent) { info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS; } - for (ConnectionRecord conn : r.connections.values()) { - if (conn.clientLabel != 0) { - info.clientPackage = conn.binding.client.info.packageName; - info.clientLabel = conn.clientLabel; - break; + + for (ArrayList<ConnectionRecord> connl : r.connections.values()) { + for (int i=0; i<connl.size(); i++) { + ConnectionRecord conn = connl.get(i); + if (conn.clientLabel != 0) { + info.clientPackage = conn.binding.client.info.packageName; + info.clientLabel = conn.clientLabel; + return info; + } } } return info; @@ -8055,9 +8115,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen synchronized (this) { ServiceRecord r = mServices.get(name); if (r != null) { - for (ConnectionRecord conn : r.connections.values()) { - if (conn.clientIntent != null) { - return conn.clientIntent; + for (ArrayList<ConnectionRecord> conn : r.connections.values()) { + for (int i=0; i<conn.size(); i++) { + if (conn.get(i).clientIntent != null) { + return conn.get(i).clientIntent; + } } } } @@ -8234,8 +8296,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen while (r.pendingStarts.size() > 0) { try { ServiceRecord.StartItem si = r.pendingStarts.remove(0); - if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to service: " - + r.name + " " + r.intent + " args=" + si.intent); + if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: " + + r + " " + r.intent + " args=" + si.intent); if (si.intent == null) { // If somehow we got a dummy start at the front, then // just drop it here. @@ -8246,8 +8308,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen si.deliveryCount++; if (si.targetPermissionUid >= 0) { grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid, - r.packageName, si.intent, si); + r.packageName, si.intent, si.getUriPermissionsLocked()); } + if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r); bumpServiceExecutingLocked(r); if (!oomAdjusted) { oomAdjusted = true; @@ -8264,6 +8327,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } catch (RemoteException e) { // Remote process gone... we'll let the normal cleanup take // care of this. + if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r); break; } catch (Exception e) { Slog.w(TAG, "Unexpected exception", e); @@ -8280,9 +8344,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } if ((!i.requested || rebind) && i.apps.size() > 0) { try { + if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r + + " in " + i + ": shouldUnbind=" + i.hasBound); bumpServiceExecutingLocked(r); - if (DEBUG_SERVICE) Slog.v(TAG, "Connecting binding " + i - + ": shouldUnbind=" + i.hasBound); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind); if (!rebind) { i.requested = true; @@ -8290,6 +8354,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen i.hasBound = true; i.doRebind = false; } catch (RemoteException e) { + if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r); return false; } } @@ -8316,13 +8381,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); app.services.add(r); + if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent); bumpServiceExecutingLocked(r); updateLruProcessLocked(app, true, true); boolean created = false; try { - if (DEBUG_SERVICE) Slog.v(TAG, "Scheduling start service: " - + r.name + " " + r.intent); mStringBuilder.setLength(0); r.intent.getIntent().toShortString(mStringBuilder, false, true); EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE, @@ -8482,8 +8546,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return true; } - if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up service " + r.name - + " " + r.intent); + if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent); // We are now bringing the service up, so no longer in the // restarting state. @@ -8534,27 +8597,30 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (!force) { // XXX should probably keep a count of the number of auto-create // connections directly in the service. - Iterator<ConnectionRecord> it = r.connections.values().iterator(); + Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { - ConnectionRecord cr = it.next(); - if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { - return; + ArrayList<ConnectionRecord> cr = it.next(); + for (int i=0; i<cr.size(); i++) { + if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) { + return; + } } } } // Report to all of the connections that the service is no longer // available. - Iterator<ConnectionRecord> it = r.connections.values().iterator(); + Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { - ConnectionRecord c = it.next(); - try { - // todo: shouldn't be a synchronous call! - c.conn.connected(r.name, null); - } catch (Exception e) { - Slog.w(TAG, "Failure disconnecting service " + r.name + - " to connection " + c.conn.asBinder() + - " (in " + c.binding.client.processName + ")", e); + ArrayList<ConnectionRecord> c = it.next(); + for (int i=0; i<c.size(); i++) { + try { + c.get(i).conn.connected(r.name, null); + } catch (Exception e) { + Slog.w(TAG, "Failure disconnecting service " + r.name + + " to connection " + c.get(i).conn.asBinder() + + " (in " + c.get(i).binding.client.processName + ")", e); + } } } } @@ -8568,6 +8634,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + ": hasBound=" + ibr.hasBound); if (r.app != null && r.app.thread != null && ibr.hasBound) { try { + if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r + + " for " + ibr); bumpServiceExecutingLocked(r); updateOomAdjLocked(r.app); ibr.hasBound = false; @@ -8582,15 +8650,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down service " + r.name - + " " + r.intent); + if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent); EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE, System.identityHashCode(r), r.shortName, (r.app != null) ? r.app.pid : -1); mServices.remove(r.name); mServicesByIntent.remove(r.intent); - if (localLOGV) Slog.v(TAG, "BRING DOWN SERVICE: " + r.shortName); r.totalRestartCount = 0; unscheduleServiceRestartLocked(r); @@ -8599,8 +8665,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen for (int i=0; i<N; i++) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); - if (DEBUG_SERVICE) Slog.v( - TAG, "Removed pending service: " + r.shortName); + if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r); i--; N--; } @@ -8622,8 +8687,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen r.app.services.remove(r); if (r.app.thread != null) { try { - if (DEBUG_SERVICE) Slog.v(TAG, - "Stopping service: " + r.shortName); + if (DEBUG_SERVICE) { + RuntimeException here = new RuntimeException(); + here.fillInStackTrace(); + Slog.v(TAG, ">>> EXECUTING stop of " + r, here); + } bumpServiceExecutingLocked(r); mStoppingServices.add(r); updateOomAdjLocked(r.app); @@ -8636,11 +8704,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen updateServiceForegroundLocked(r.app, false); } else { if (DEBUG_SERVICE) Slog.v( - TAG, "Removed service that has no process: " + r.shortName); + TAG, "Removed service that has no process: " + r); } } else { if (DEBUG_SERVICE) Slog.v( - TAG, "Removed service that is not running: " + r.shortName); + TAG, "Removed service that is not running: " + r); } } @@ -8675,8 +8743,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen int targetPermissionUid = checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service); if (unscheduleServiceRestartLocked(r)) { - if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " - + r.shortName); + if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r); } r.startRequested = true; r.callStart = false; @@ -8970,7 +9037,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (unscheduleServiceRestartLocked(s)) { if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: " - + s.shortName); + + s); } AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); @@ -8978,7 +9045,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen connection, flags, clientLabel, clientIntent); IBinder binder = connection.asBinder(); - s.connections.put(binder, c); + ArrayList<ConnectionRecord> clist = s.connections.get(binder); + if (clist == null) { + clist = new ArrayList<ConnectionRecord>(); + s.connections.put(binder, clist); + } + clist.add(c); b.connections.add(c); if (activity != null) { if (activity.connections == null) { @@ -8987,7 +9059,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen activity.connections.add(c); } b.client.connections.add(c); - mServiceConnections.put(binder, c); + clist = mServiceConnections.get(binder); + if (clist == null) { + clist = new ArrayList<ConnectionRecord>(); + mServiceConnections.put(binder, clist); + } + clist.add(c); if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); @@ -9038,7 +9115,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; - s.connections.remove(binder); + ArrayList<ConnectionRecord> clist = s.connections.get(binder); + if (clist != null) { + clist.remove(c); + if (clist.size() == 0) { + s.connections.remove(binder); + } + } b.connections.remove(c); if (c.activity != null && c.activity != skipAct) { if (c.activity.connections != null) { @@ -9048,7 +9131,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (b.client != skipApp) { b.client.connections.remove(c); } - mServiceConnections.remove(binder); + clist = mServiceConnections.get(binder); + if (clist != null) { + clist.remove(c); + if (clist.size() == 0) { + mServiceConnections.remove(binder); + } + } if (b.connections.size() == 0) { b.intent.apps.remove(b.client); @@ -9059,6 +9148,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { + if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s + + " from " + b); bumpServiceExecutingLocked(s); updateOomAdjLocked(s.app); b.intent.hasBound = false; @@ -9081,8 +9172,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen synchronized (this) { IBinder binder = connection.asBinder(); if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder); - ConnectionRecord r = mServiceConnections.get(binder); - if (r == null) { + ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); + if (clist == null) { Slog.w(TAG, "Unbind failed: could not find connection for " + connection.asBinder()); return false; @@ -9090,11 +9181,14 @@ public final class ActivityManagerService extends ActivityManagerNative implemen final long origId = Binder.clearCallingIdentity(); - removeConnectionLocked(r, null, null); + while (clist.size() > 0) { + ConnectionRecord r = clist.get(0); + removeConnectionLocked(r, null, null); - if (r.binding.service.app != null) { - // This could have made the service less important. - updateOomAdjLocked(r.binding.service.app); + if (r.binding.service.app != null) { + // This could have made the service less important. + updateOomAdjLocked(r.binding.service.app); + } } Binder.restoreCallingIdentity(origId); @@ -9117,7 +9211,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen final long origId = Binder.clearCallingIdentity(); - if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING SERVICE " + r.name + if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r + " " + intent + ": " + service); if (r != null) { Intent.FilterComparison filter @@ -9128,26 +9222,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen b.requested = true; b.received = true; if (r.connections.size() > 0) { - Iterator<ConnectionRecord> it + Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { - ConnectionRecord c = it.next(); - if (!filter.equals(c.binding.intent.intent)) { - if (DEBUG_SERVICE) Slog.v( - TAG, "Not publishing to: " + c); - if (DEBUG_SERVICE) Slog.v( - TAG, "Bound intent: " + c.binding.intent.intent); - if (DEBUG_SERVICE) Slog.v( - TAG, "Published intent: " + intent); - continue; - } - if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c); - try { - c.conn.connected(r.name, service); - } catch (Exception e) { - Slog.w(TAG, "Failure sending service " + r.name + - " to connection " + c.conn.asBinder() + - " (in " + c.binding.client.processName + ")", e); + ArrayList<ConnectionRecord> clist = it.next(); + for (int i=0; i<clist.size(); i++) { + ConnectionRecord c = clist.get(i); + if (!filter.equals(c.binding.intent.intent)) { + if (DEBUG_SERVICE) Slog.v( + TAG, "Not publishing to: " + c); + if (DEBUG_SERVICE) Slog.v( + TAG, "Bound intent: " + c.binding.intent.intent); + if (DEBUG_SERVICE) Slog.v( + TAG, "Published intent: " + intent); + continue; + } + if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c); + try { + c.conn.connected(r.name, service); + } catch (Exception e) { + Slog.w(TAG, "Failure sending service " + r.name + + " to connection " + c.conn.asBinder() + + " (in " + c.binding.client.processName + ")", e); + } } } } @@ -9208,9 +9305,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen ServiceRecord r = (ServiceRecord)token; boolean inStopping = mStoppingServices.contains(token); if (r != null) { - if (DEBUG_SERVICE) Slog.v(TAG, "DONE EXECUTING SERVICE " + r.name - + ": nesting=" + r.executeNesting - + ", inStopping=" + inStopping); if (r != token) { Slog.w(TAG, "Done executing service " + r.name + " with incorrect token: given " + token @@ -9267,13 +9361,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen serviceDoneExecutingLocked(r, inStopping); Binder.restoreCallingIdentity(origId); } else { - Slog.w(TAG, "Done executing unknown service " + r.name - + " with token " + token); + Slog.w(TAG, "Done executing unknown service from pid " + + Binder.getCallingPid()); } } } public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) { + if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r + + ": nesting=" + r.executeNesting + + ", inStopping=" + inStopping + ", app=" + r.app); r.executeNesting--; if (r.executeNesting <= 0 && r.app != null) { r.app.executingServices.remove(r); @@ -9281,6 +9378,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app); } if (inStopping) { + if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r); mStoppingServices.remove(r); } updateOomAdjLocked(r.app); @@ -11071,61 +11169,64 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) { - Iterator<ConnectionRecord> kt + Iterator<ArrayList<ConnectionRecord>> kt = s.connections.values().iterator(); while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) { - // XXX should compute this based on the max of - // all connected clients. - ConnectionRecord cr = kt.next(); - if (cr.binding.client == app) { - // Binding to ourself is not interesting. - continue; - } - if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { - ProcessRecord client = cr.binding.client; - int myHiddenAdj = hiddenAdj; - if (myHiddenAdj > client.hiddenAdj) { - if (client.hiddenAdj >= VISIBLE_APP_ADJ) { - myHiddenAdj = client.hiddenAdj; - } else { - myHiddenAdj = VISIBLE_APP_ADJ; - } + ArrayList<ConnectionRecord> clist = kt.next(); + for (int i=0; i<clist.size() && adj > FOREGROUND_APP_ADJ; i++) { + // XXX should compute this based on the max of + // all connected clients. + ConnectionRecord cr = clist.get(i); + if (cr.binding.client == app) { + // Binding to ourself is not interesting. + continue; } - int clientAdj = computeOomAdjLocked( - client, myHiddenAdj, TOP_APP, true); - if (adj > clientAdj) { - adj = clientAdj >= VISIBLE_APP_ADJ - ? clientAdj : VISIBLE_APP_ADJ; - if (!client.hidden) { - app.hidden = false; + if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { + ProcessRecord client = cr.binding.client; + int myHiddenAdj = hiddenAdj; + if (myHiddenAdj > client.hiddenAdj) { + if (client.hiddenAdj >= VISIBLE_APP_ADJ) { + myHiddenAdj = client.hiddenAdj; + } else { + myHiddenAdj = VISIBLE_APP_ADJ; + } + } + int clientAdj = computeOomAdjLocked( + client, myHiddenAdj, TOP_APP, true); + if (adj > clientAdj) { + adj = clientAdj >= VISIBLE_APP_ADJ + ? clientAdj : VISIBLE_APP_ADJ; + if (!client.hidden) { + app.hidden = false; + } + app.adjType = "service"; + app.adjTypeCode = ActivityManager.RunningAppProcessInfo + .REASON_SERVICE_IN_USE; + app.adjSource = cr.binding.client; + app.adjTarget = s.name; } + if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { + if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) { + schedGroup = Process.THREAD_GROUP_DEFAULT; + } + } + } + ActivityRecord a = cr.activity; + //if (a != null) { + // Slog.i(TAG, "Connection to " + a ": state=" + a.state); + //} + if (a != null && adj > FOREGROUND_APP_ADJ && + (a.state == ActivityState.RESUMED + || a.state == ActivityState.PAUSING)) { + adj = FOREGROUND_APP_ADJ; + schedGroup = Process.THREAD_GROUP_DEFAULT; + app.hidden = false; app.adjType = "service"; app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; - app.adjSource = cr.binding.client; + app.adjSource = a; app.adjTarget = s.name; } - if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) { - if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) { - schedGroup = Process.THREAD_GROUP_DEFAULT; - } - } - } - ActivityRecord a = cr.activity; - //if (a != null) { - // Slog.i(TAG, "Connection to " + a ": state=" + a.state); - //} - if (a != null && adj > FOREGROUND_APP_ADJ && - (a.state == ActivityState.RESUMED - || a.state == ActivityState.PAUSING)) { - adj = FOREGROUND_APP_ADJ; - schedGroup = Process.THREAD_GROUP_DEFAULT; - app.hidden = false; - app.adjType = "service"; - app.adjTypeCode = ActivityManager.RunningAppProcessInfo - .REASON_SERVICE_IN_USE; - app.adjSource = a; - app.adjTarget = s.name; } } } diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 80a41b7..62be918 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -44,7 +44,7 @@ import java.util.HashSet; /** * An entry in the history stack, representing an activity. */ -class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwner { +class ActivityRecord extends IApplicationToken.Stub { final ActivityManagerService service; // owner final ActivityStack stack; // owner final ActivityInfo info; // all about me @@ -78,8 +78,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act ArrayList newIntents; // any pending new intents for single-top mode HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + UriPermissionOwner uriPermissions; // current special URI access perms. ProcessRecord app; // if non-null, hosting application Bitmap thumbnail; // icon representation of paused screen CharSequence description; // textual description of paused screen @@ -141,11 +140,15 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne if (pendingResults != null) { pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults); } - if (readUriPermissions != null) { - pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions); - } - if (writeUriPermissions != null) { - pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions); + if (uriPermissions != null) { + if (uriPermissions.readUriPermissions != null) { + pw.print(prefix); pw.print("readUriPermissions="); + pw.println(uriPermissions.readUriPermissions); + } + if (uriPermissions.writeUriPermissions != null) { + pw.print(prefix); pw.print("writeUriPermissions="); + pw.println(uriPermissions.writeUriPermissions); + } } pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed); pw.print(" haveState="); pw.print(haveState); @@ -301,6 +304,13 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } } + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(service, this); + } + return uriPermissions; + } + void addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData) { @@ -350,7 +360,7 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne intent = new Intent(intent); ar.add(intent); service.grantUriPermissionFromIntentLocked(callingUid, packageName, - intent, this); + intent, getUriPermissionsLocked()); app.thread.scheduleNewIntent(ar, this); sent = true; } catch (RemoteException e) { @@ -367,27 +377,9 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne } void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - service.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -578,38 +570,6 @@ class ActivityRecord extends IApplicationToken.Stub implements UriPermissionOwne state == ActivityState.RESUMED; } - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); - } - readUriPermissions.add(perm); - } - - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; - } - } - public String toString() { if (stringName != null) { return stringName; diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a5f7e96..a99b48c 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -2327,12 +2327,12 @@ public class ActivityStack { if (grantedUriPermissions != null && callingUid > 0) { for (int i=0; i<grantedUriPermissions.length; i++) { mService.grantUriPermissionLocked(callingUid, r.packageName, - grantedUriPermissions[i], grantedMode, r); + grantedUriPermissions[i], grantedMode, r.getUriPermissionsLocked()); } } mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - intent, r); + intent, r.getUriPermissionsLocked()); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId); @@ -2557,7 +2557,7 @@ public class ActivityStack { if (callingUid > 0) { mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, - data, r); + data, r.getUriPermissionsLocked()); } if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r @@ -2885,7 +2885,7 @@ public class ActivityStack { + " res=" + resultCode + " data=" + resultData); if (r.info.applicationInfo.uid > 0) { mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, - r.packageName, resultData, r); + r.packageName, resultData, r.getUriPermissionsLocked()); } resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index 255fbe3..f35a68e 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -72,8 +72,8 @@ class ServiceRecord extends Binder { final HashMap<Intent.FilterComparison, IntentBindRecord> bindings = new HashMap<Intent.FilterComparison, IntentBindRecord>(); // All active bindings to the service. - final HashMap<IBinder, ConnectionRecord> connections - = new HashMap<IBinder, ConnectionRecord>(); + final HashMap<IBinder, ArrayList<ConnectionRecord>> connections + = new HashMap<IBinder, ArrayList<ConnectionRecord>>(); // IBinder -> ConnectionRecord of all bound clients ProcessRecord app; // where this service is running or null. @@ -96,7 +96,7 @@ class ServiceRecord extends Binder { String stringName; // caching of toString - static class StartItem implements UriPermissionOwner { + static class StartItem { final ServiceRecord sr; final int id; final Intent intent; @@ -104,12 +104,10 @@ class ServiceRecord extends Binder { long deliveredTime; int deliveryCount; int doneExecutingCount; + UriPermissionOwner uriPermissions; String stringName; // caching of toString - HashSet<UriPermission> readUriPermissions; // special access to reading uris. - HashSet<UriPermission> writeUriPermissions; // special access to writing uris. - StartItem(ServiceRecord _sr, int _id, Intent _intent, int _targetPermissionUid) { sr = _sr; id = _id; @@ -117,60 +115,17 @@ class ServiceRecord extends Binder { targetPermissionUid = _targetPermissionUid; } - void removeUriPermissionsLocked() { - if (readUriPermissions != null) { - for (UriPermission perm : readUriPermissions) { - perm.readOwners.remove(this); - if (perm.readOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - readUriPermissions = null; - } - if (writeUriPermissions != null) { - for (UriPermission perm : writeUriPermissions) { - perm.writeOwners.remove(this); - if (perm.writeOwners.size() == 0 && (perm.globalModeFlags - &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { - perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; - sr.ams.removeUriPermissionIfNeededLocked(perm); - } - } - writeUriPermissions = null; + UriPermissionOwner getUriPermissionsLocked() { + if (uriPermissions == null) { + uriPermissions = new UriPermissionOwner(sr.ams, this); } + return uriPermissions; } - @Override - public void addReadPermission(UriPermission perm) { - if (readUriPermissions == null) { - readUriPermissions = new HashSet<UriPermission>(); - } - readUriPermissions.add(perm); - } - - @Override - public void addWritePermission(UriPermission perm) { - if (writeUriPermissions == null) { - writeUriPermissions = new HashSet<UriPermission>(); - } - writeUriPermissions.add(perm); - } - - @Override - public void removeReadPermission(UriPermission perm) { - readUriPermissions.remove(perm); - if (readUriPermissions.size() == 0) { - readUriPermissions = null; - } - } - - @Override - public void removeWritePermission(UriPermission perm) { - writeUriPermissions.remove(perm); - if (writeUriPermissions.size() == 0) { - writeUriPermissions = null; + void removeUriPermissionsLocked() { + if (uriPermissions != null) { + uriPermissions.removeUriPermissionsLocked(); + uriPermissions = null; } } @@ -218,13 +173,15 @@ class ServiceRecord extends Binder { pw.print(prefix); pw.print(" targetPermissionUid="); pw.println(si.targetPermissionUid); } - if (si.readUriPermissions != null) { - pw.print(prefix); pw.print(" readUriPermissions="); - pw.println(si.readUriPermissions); - } - if (si.writeUriPermissions != null) { - pw.print(prefix); pw.print(" writeUriPermissions="); - pw.println(si.writeUriPermissions); + if (si.uriPermissions != null) { + if (si.uriPermissions.readUriPermissions != null) { + pw.print(prefix); pw.print(" readUriPermissions="); + pw.println(si.uriPermissions.readUriPermissions); + } + if (si.uriPermissions.writeUriPermissions != null) { + pw.print(prefix); pw.print(" writeUriPermissions="); + pw.println(si.uriPermissions.writeUriPermissions); + } } } } @@ -296,10 +253,12 @@ class ServiceRecord extends Binder { } if (connections.size() > 0) { pw.print(prefix); pw.println("All Connections:"); - Iterator<ConnectionRecord> it = connections.values().iterator(); + Iterator<ArrayList<ConnectionRecord>> it = connections.values().iterator(); while (it.hasNext()) { - ConnectionRecord c = it.next(); - pw.print(prefix); pw.print(" "); pw.println(c); + ArrayList<ConnectionRecord> c = it.next(); + for (int i=0; i<c.size(); i++) { + pw.print(prefix); pw.print(" "); pw.println(c.get(i)); + } } } } diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java index 93c59cc..c95546e 100644 --- a/services/java/com/android/server/am/UriPermission.java +++ b/services/java/com/android/server/am/UriPermission.java @@ -22,13 +22,14 @@ import android.net.Uri; import java.io.PrintWriter; import java.util.HashSet; -interface UriPermissionOwner { - void addReadPermission(UriPermission perm); - void addWritePermission(UriPermission perm); - void removeReadPermission(UriPermission perm); - void removeWritePermission(UriPermission perm); -} - +/** + * Description of a permission granted to an app to access a particular URI. + * + * CTS tests for this functionality can be run with "runtest cts-appsecurity". + * + * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert + * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java + */ class UriPermission { final int uid; final Uri uri; diff --git a/services/java/com/android/server/am/UriPermissionOwner.java b/services/java/com/android/server/am/UriPermissionOwner.java new file mode 100644 index 0000000..99c82e6 --- /dev/null +++ b/services/java/com/android/server/am/UriPermissionOwner.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010 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.am; + +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.IBinder; + +import java.util.HashSet; +import java.util.Iterator; + +class UriPermissionOwner { + final ActivityManagerService service; + final Object owner; + + Binder externalToken; + + HashSet<UriPermission> readUriPermissions; // special access to reading uris. + HashSet<UriPermission> writeUriPermissions; // special access to writing uris. + + class ExternalToken extends Binder { + UriPermissionOwner getOwner() { + return UriPermissionOwner.this; + } + } + + UriPermissionOwner(ActivityManagerService _service, Object _owner) { + service = _service; + owner = _owner; + } + + Binder getExternalTokenLocked() { + if (externalToken != null) { + externalToken = new ExternalToken(); + } + return externalToken; + } + + static UriPermissionOwner fromExternalToken(IBinder token) { + if (token instanceof ExternalToken) { + return ((ExternalToken)token).getOwner(); + } + return null; + } + + void removeUriPermissionsLocked() { + removeUriPermissionsLocked(Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + + void removeUriPermissionsLocked(int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + for (UriPermission perm : readUriPermissions) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + readUriPermissions = null; + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + for (UriPermission perm : writeUriPermissions) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + } + writeUriPermissions = null; + } + } + + void removeUriPermissionLocked(Uri uri, int mode) { + if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0 + && readUriPermissions != null) { + Iterator<UriPermission> it = readUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.readOwners.remove(this); + if (perm.readOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_READ_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0 + && writeUriPermissions != null) { + Iterator<UriPermission> it = writeUriPermissions.iterator(); + while (it.hasNext()) { + UriPermission perm = it.next(); + if (uri.equals(perm.uri)) { + perm.writeOwners.remove(this); + if (perm.writeOwners.size() == 0 && (perm.globalModeFlags + &Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) { + perm.modeFlags &= ~Intent.FLAG_GRANT_WRITE_URI_PERMISSION; + service.removeUriPermissionIfNeededLocked(perm); + } + it.remove(); + } + } + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + } + + public void addReadPermission(UriPermission perm) { + if (readUriPermissions == null) { + readUriPermissions = new HashSet<UriPermission>(); + } + readUriPermissions.add(perm); + } + + public void addWritePermission(UriPermission perm) { + if (writeUriPermissions == null) { + writeUriPermissions = new HashSet<UriPermission>(); + } + writeUriPermissions.add(perm); + } + + public void removeReadPermission(UriPermission perm) { + readUriPermissions.remove(perm); + if (readUriPermissions.size() == 0) { + readUriPermissions = null; + } + } + + public void removeWritePermission(UriPermission perm) { + writeUriPermissions.remove(perm); + if (writeUriPermissions.size() == 0) { + writeUriPermissions = null; + } + } + + @Override + public String toString() { + return owner.toString(); + } +} diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java index 1142136..3dcaff6 100644 --- a/services/java/com/android/server/sip/SipService.java +++ b/services/java/com/android/server/sip/SipService.java @@ -32,6 +32,7 @@ import android.net.sip.SipProfile; import android.net.sip.SipSessionAdapter; import android.net.sip.SipSessionState; import android.net.wifi.WifiManager; +import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.SystemClock; @@ -97,6 +98,7 @@ public final class SipService extends ISipService.Stub { } public void open(SipProfile localProfile) { + localProfile.setCallingUid(Binder.getCallingUid()); if (localProfile.getAutoRegistration()) { openToReceiveCalls(localProfile); } else { @@ -119,6 +121,7 @@ public final class SipService extends ISipService.Stub { public synchronized void open3(SipProfile localProfile, String incomingCallBroadcastAction, ISipSessionListener listener) { + localProfile.setCallingUid(Binder.getCallingUid()); if (TextUtils.isEmpty(incomingCallBroadcastAction)) { throw new RuntimeException( "empty broadcast action for incoming call"); @@ -165,6 +168,7 @@ public final class SipService extends ISipService.Stub { public synchronized ISipSession createSession(SipProfile localProfile, ISipSessionListener listener) { + localProfile.setCallingUid(Binder.getCallingUid()); if (!mConnected) return null; try { SipSessionGroupExt group = createGroup(localProfile); @@ -362,16 +366,7 @@ public final class SipService extends ISipService.Stub { private SipProfile duplicate(SipProfile p) { try { - return new SipProfile.Builder(p.getUserName(), p.getSipDomain()) - .setProfileName(p.getProfileName()) - .setPassword("*") - .setPort(p.getPort()) - .setProtocol(p.getProtocol()) - .setOutboundProxy(p.getProxyAddress()) - .setSendKeepAlive(p.getSendKeepAlive()) - .setAutoRegistration(p.getAutoRegistration()) - .setDisplayName(p.getDisplayName()) - .build(); + return new SipProfile.Builder(p).setPassword("*").build(); } catch (Exception e) { Log.wtf(TAG, "duplicate()", e); throw new RuntimeException("duplicate profile", e); |
