summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml113
-rw-r--r--camera/libcameraservice/CameraService.cpp11
-rw-r--r--camera/libcameraservice/CameraService.h4
-rw-r--r--core/java/android/content/ContentProvider.java136
-rw-r--r--core/java/android/content/pm/PackageParser.java98
-rw-r--r--core/java/android/content/pm/PathPermission.java68
-rw-r--r--core/java/android/content/pm/ProviderInfo.java12
-rw-r--r--core/java/android/speech/tts/TextToSpeech.java1
-rw-r--r--core/jni/android_hardware_Camera.cpp7
-rw-r--r--core/res/AndroidManifest.xml23
-rw-r--r--core/res/res/values/attrs_manifest.xml14
-rw-r--r--include/ui/Camera.h3
-rw-r--r--include/ui/CameraHardwareInterface.h2
-rw-r--r--include/ui/ICameraClient.h3
-rw-r--r--libs/ui/Camera.cpp13
-rw-r--r--libs/ui/ICameraClient.cpp23
-rw-r--r--services/java/com/android/server/NotificationManagerService.java16
-rw-r--r--services/java/com/android/server/SystemServer.java10
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java22
19 files changed, 537 insertions, 42 deletions
diff --git a/api/current.xml b/api/current.xml
index d97a0f4..a396c4d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -496,6 +496,17 @@
visibility="public"
>
</field>
+<field name="GLOBAL_SEARCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.GLOBAL_SEARCH&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="HARDWARE_TEST"
type="java.lang.String"
transient="false"
@@ -25945,6 +25956,17 @@
visibility="public"
>
</method>
+<method name="getPathPermissions"
+ return="android.content.pm.PathPermission[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getReadPermission"
return="java.lang.String"
abstract="false"
@@ -26113,6 +26135,19 @@
<parameter name="sortOrder" type="java.lang.String">
</parameter>
</method>
+<method name="setPathPermissions"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="permissions" type="android.content.pm.PathPermission[]">
+</parameter>
+</method>
<method name="setReadPermission"
return="void"
abstract="false"
@@ -37714,6 +37749,73 @@
>
</field>
</class>
+<class name="PathPermission"
+ extends="android.os.PatternMatcher"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PathPermission"
+ type="android.content.pm.PathPermission"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="pattern" type="java.lang.String">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+<parameter name="readPermission" type="java.lang.String">
+</parameter>
+<parameter name="writePermission" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="PathPermission"
+ type="android.content.pm.PathPermission"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="src" type="android.os.Parcel">
+</parameter>
+</constructor>
+<method name="getReadPermission"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWritePermission"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="PermissionGroupInfo"
extends="android.content.pm.PackageItemInfo"
abstract="false"
@@ -38043,6 +38145,17 @@
visibility="public"
>
</field>
+<field name="pathPermissions"
+ type="android.content.pm.PathPermission[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="readPermission"
type="java.lang.String"
transient="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 022fe5a..e4b6791 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -504,8 +504,7 @@ status_t CameraService::Client::startRecordingMode()
}
// start recording mode
- ret = mHardware->startRecording(recordingCallback,
- mCameraService.get());
+ ret = mHardware->startRecording(recordingCallback, mCameraService.get());
if (ret != NO_ERROR) {
LOGE("mHardware->startRecording() failed with status %d", ret);
}
@@ -798,7 +797,7 @@ void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
}
// recording callback
-void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user)
+void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user)
{
LOGV("recordingCallback");
sp<Client> client = getClientFromCookie(user);
@@ -806,7 +805,7 @@ void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user
return;
}
// The strong pointer guarantees the client will exist, but no lock is held.
- client->postRecordingFrame(mem);
+ client->postRecordingFrame(timestamp, mem);
}
// take a picture - image is returned in callback
@@ -1072,14 +1071,14 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, si
mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
}
-void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame)
+void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame)
{
LOGV("postRecordingFrame");
if (frame == 0) {
LOGW("frame is a null pointer");
return;
}
- mCameraClient->dataCallback(CAMERA_MSG_VIDEO_FRAME, frame);
+ mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame);
}
void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 0f07673..ea93789 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -132,7 +132,7 @@ private:
status_t checkPid();
- static void recordingCallback(const sp<IMemory>& mem, void* user);
+ static void recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
static void previewCallback(const sp<IMemory>& mem, void* user);
static void shutterCallback(void *user);
static void yuvPictureCallback(const sp<IMemory>& mem, void* user);
@@ -144,7 +144,7 @@ private:
void postRaw(const sp<IMemory>& mem);
void postJpeg(const sp<IMemory>& mem);
void postPreviewFrame(const sp<IMemory>& mem);
- void postRecordingFrame(const sp<IMemory>& frame);
+ void postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame);
void copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
void postError(status_t error);
void postAutoFocus(bool focused);
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 5cc5730..6b50405 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -17,6 +17,7 @@
package android.content;
import android.content.pm.PackageManager;
+import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
@@ -29,6 +30,7 @@ import android.database.SQLException;
import android.net.Uri;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import java.io.File;
import java.io.FileNotFoundException;
@@ -65,8 +67,10 @@ import java.io.FileNotFoundException;
*/
public abstract class ContentProvider implements ComponentCallbacks {
private Context mContext = null;
+ private int mMyUid;
private String mReadPermission;
private String mWritePermission;
+ private PathPermission[] mPathPermissions;
private Transport mTransport = new Transport();
@@ -108,24 +112,20 @@ public abstract class ContentProvider implements ComponentCallbacks {
public IBulkCursor bulkQuery(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
IContentObserver observer, CursorWindow window) {
- checkReadPermission(uri);
+ enforceReadPermission(uri);
Cursor cursor = ContentProvider.this.query(uri, projection,
selection, selectionArgs, sortOrder);
if (cursor == null) {
return null;
}
- String wperm = getWritePermission();
return new CursorToBulkCursorAdaptor(cursor, observer,
ContentProvider.this.getClass().getName(),
- wperm == null ||
- getContext().checkCallingOrSelfPermission(getWritePermission())
- == PackageManager.PERMISSION_GRANTED,
- window);
+ hasWritePermission(uri), window);
}
public Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
- checkReadPermission(uri);
+ enforceReadPermission(uri);
return ContentProvider.this.query(uri, projection, selection,
selectionArgs, sortOrder);
}
@@ -136,55 +136,84 @@ public abstract class ContentProvider implements ComponentCallbacks {
public Uri insert(Uri uri, ContentValues initialValues) {
- checkWritePermission(uri);
+ enforceWritePermission(uri);
return ContentProvider.this.insert(uri, initialValues);
}
public int bulkInsert(Uri uri, ContentValues[] initialValues) {
- checkWritePermission(uri);
+ enforceWritePermission(uri);
return ContentProvider.this.bulkInsert(uri, initialValues);
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
- checkWritePermission(uri);
+ enforceWritePermission(uri);
return ContentProvider.this.delete(uri, selection, selectionArgs);
}
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- checkWritePermission(uri);
+ enforceWritePermission(uri);
return ContentProvider.this.update(uri, values, selection, selectionArgs);
}
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
- if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
- else checkReadPermission(uri);
+ if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
+ else enforceReadPermission(uri);
return ContentProvider.this.openFile(uri, mode);
}
public AssetFileDescriptor openAssetFile(Uri uri, String mode)
throws FileNotFoundException {
- if (mode != null && mode.startsWith("rw")) checkWritePermission(uri);
- else checkReadPermission(uri);
+ if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri);
+ else enforceReadPermission(uri);
return ContentProvider.this.openAssetFile(uri, mode);
}
public ISyncAdapter getSyncAdapter() {
- checkWritePermission(null);
+ enforceWritePermission(null);
SyncAdapter sa = ContentProvider.this.getSyncAdapter();
return sa != null ? sa.getISyncAdapter() : null;
}
- private void checkReadPermission(Uri uri) {
+ private void enforceReadPermission(Uri uri) {
+ final int uid = Binder.getCallingUid();
+ if (uid == mMyUid) {
+ return;
+ }
+
+ final Context context = getContext();
final String rperm = getReadPermission();
final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- if (getContext().checkUriPermission(uri, rperm, null, pid, uid,
+ if (rperm == null
+ || context.checkPermission(rperm, pid, uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ PathPermission[] pps = getPathPermissions();
+ if (pps != null) {
+ final String path = uri.getPath();
+ int i = pps.length;
+ while (i > 0) {
+ i--;
+ final PathPermission pp = pps[i];
+ final String pprperm = pp.getReadPermission();
+ if (pprperm != null && pp.match(path)) {
+ if (context.checkPermission(pprperm, pid, uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ }
+ }
+
+ if (context.checkUriPermission(uri, pid, uid,
Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PackageManager.PERMISSION_GRANTED) {
return;
}
+
String msg = "Permission Denial: reading "
+ ContentProvider.this.getClass().getName()
+ " uri " + uri + " from pid=" + Binder.getCallingPid()
@@ -193,20 +222,57 @@ public abstract class ContentProvider implements ComponentCallbacks {
throw new SecurityException(msg);
}
- private void checkWritePermission(Uri uri) {
+ private boolean hasWritePermission(Uri uri) {
+ final int uid = Binder.getCallingUid();
+ if (uid == mMyUid) {
+ return true;
+ }
+
+ final Context context = getContext();
final String wperm = getWritePermission();
final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- if (getContext().checkUriPermission(uri, null, wperm, pid, uid,
+ if (wperm == null
+ || context.checkPermission(wperm, pid, uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
+ PathPermission[] pps = getPathPermissions();
+ if (pps != null) {
+ final String path = uri.getPath();
+ int i = pps.length;
+ while (i > 0) {
+ i--;
+ final PathPermission pp = pps[i];
+ final String ppwperm = pp.getWritePermission();
+ if (ppwperm != null && pp.match(path)) {
+ if (context.checkPermission(ppwperm, pid, uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ }
+ }
+ }
+
+ if (context.checkUriPermission(uri, pid, uid,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
== PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void enforceWritePermission(Uri uri) {
+ if (hasWritePermission(uri)) {
return;
}
+
String msg = "Permission Denial: writing "
+ ContentProvider.this.getClass().getName()
+ " uri " + uri + " from pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
- + " requires " + wperm;
+ + " requires " + getWritePermission();
throw new SecurityException(msg);
}
}
@@ -266,6 +332,28 @@ public abstract class ContentProvider implements ComponentCallbacks {
}
/**
+ * Change the path-based permission required to read and/or write data in
+ * the content provider. This is normally set for you from its manifest
+ * information when the provider is first created.
+ *
+ * @param permissions Array of path permission descriptions.
+ */
+ protected final void setPathPermissions(PathPermission[] permissions) {
+ mPathPermissions = permissions;
+ }
+
+ /**
+ * Return the path-based permissions required for read and/or write access to
+ * this content provider. This method can be called from multiple
+ * threads, as described in
+ * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
+ * Processes and Threads</a>.
+ */
+ public final PathPermission[] getPathPermissions() {
+ return mPathPermissions;
+ }
+
+ /**
* Called when the provider is being started.
*
* @return true if the provider was successfully loaded, false otherwise
@@ -600,9 +688,11 @@ public abstract class ContentProvider implements ComponentCallbacks {
*/
if (mContext == null) {
mContext = context;
+ mMyUid = Process.myUid();
if (info != null) {
setReadPermission(info.readPermission);
setWritePermission(info.writePermission);
+ setPathPermissions(info.pathPermissions);
}
ContentProvider.this.onCreate();
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b293636..0e2deed 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1918,6 +1918,7 @@ public class PackageParser {
outInfo.metaData, outError)) == null) {
return false;
}
+
} else if (parser.getName().equals("grant-uri-permission")) {
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestGrantUriPermission);
@@ -1941,7 +1942,7 @@ public class PackageParser {
if (str != null) {
pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
}
-
+
sa.recycle();
if (pa != null) {
@@ -1956,6 +1957,101 @@ public class PackageParser {
outInfo.info.uriPermissionPatterns = newp;
}
outInfo.info.grantUriPermissions = true;
+ } else {
+ if (!RIGID_PARSER) {
+ Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
+ Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>");
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
+ return false;
+ }
+ XmlUtils.skipCurrentTag(parser);
+
+ } else if (parser.getName().equals("path-permission")) {
+ TypedArray sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestPathPermission);
+
+ PathPermission pa = null;
+
+ String permission = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_permission);
+ String readPermission = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission);
+ if (readPermission == null) {
+ readPermission = permission;
+ }
+ String writePermission = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission);
+ if (writePermission == null) {
+ writePermission = permission;
+ }
+
+ boolean havePerm = false;
+ if (readPermission != null) {
+ readPermission = readPermission.intern();
+ havePerm = true;
+ }
+ if (writePermission != null) {
+ writePermission = readPermission.intern();
+ havePerm = true;
+ }
+
+ if (!havePerm) {
+ if (!RIGID_PARSER) {
+ Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
+ Log.w(TAG, "No readPermission or writePermssion for <path-permission>");
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ outError[0] = "No readPermission or writePermssion for <path-permission>";
+ return false;
+ }
+
+ String path = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_path);
+ if (path != null) {
+ pa = new PathPermission(path,
+ PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
+ }
+
+ path = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix);
+ if (path != null) {
+ pa = new PathPermission(path,
+ PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
+ }
+
+ path = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern);
+ if (path != null) {
+ pa = new PathPermission(path,
+ PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
+ }
+
+ sa.recycle();
+
+ if (pa != null) {
+ if (outInfo.info.pathPermissions == null) {
+ outInfo.info.pathPermissions = new PathPermission[1];
+ outInfo.info.pathPermissions[0] = pa;
+ } else {
+ final int N = outInfo.info.pathPermissions.length;
+ PathPermission[] newp = new PathPermission[N+1];
+ System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N);
+ newp[N] = pa;
+ outInfo.info.pathPermissions = newp;
+ }
+ } else {
+ if (!RIGID_PARSER) {
+ Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
+ Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>");
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
+ return false;
}
XmlUtils.skipCurrentTag(parser);
diff --git a/core/java/android/content/pm/PathPermission.java b/core/java/android/content/pm/PathPermission.java
new file mode 100644
index 0000000..7e49d7d
--- /dev/null
+++ b/core/java/android/content/pm/PathPermission.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 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 android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PatternMatcher;
+
+/**
+ * Description of permissions needed to access a particular path
+ * in a {@link ProviderInfo}.
+ */
+public class PathPermission extends PatternMatcher {
+ private final String mReadPermission;
+ private final String mWritePermission;
+
+ public PathPermission(String pattern, int type, String readPermission,
+ String writePermission) {
+ super(pattern, type);
+ mReadPermission = readPermission;
+ mWritePermission = writePermission;
+ }
+
+ public String getReadPermission() {
+ return mReadPermission;
+ }
+
+ public String getWritePermission() {
+ return mWritePermission;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mReadPermission);
+ dest.writeString(mWritePermission);
+ }
+
+ public PathPermission(Parcel src) {
+ super(src);
+ mReadPermission = src.readString();
+ mWritePermission = src.readString();
+ }
+
+ public static final Parcelable.Creator<PathPermission> CREATOR
+ = new Parcelable.Creator<PathPermission>() {
+ public PathPermission createFromParcel(Parcel source) {
+ return new PathPermission(source);
+ }
+
+ public PathPermission[] newArray(int size) {
+ return new PathPermission[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java
index b67ddf6..d01460e 100644
--- a/core/java/android/content/pm/ProviderInfo.java
+++ b/core/java/android/content/pm/ProviderInfo.java
@@ -28,6 +28,7 @@ import android.os.PatternMatcher;
*/
public final class ProviderInfo extends ComponentInfo
implements Parcelable {
+
/** The name provider is published under content:// */
public String authority = null;
@@ -56,6 +57,14 @@ public final class ProviderInfo extends ComponentInfo
*/
public PatternMatcher[] uriPermissionPatterns = null;
+ /**
+ * If non-null, these are path-specific permissions that are allowed for
+ * accessing the provider. Any permissions listed here will allow a
+ * holding client to access the provider, and the provider will check
+ * the URI it provides when making calls against the patterns here.
+ */
+ public PathPermission[] pathPermissions = null;
+
/** If true, this content provider allows multiple instances of itself
* to run in different process. If false, a single instances is always
* run in {@link #processName}. */
@@ -78,6 +87,7 @@ public final class ProviderInfo extends ComponentInfo
writePermission = orig.writePermission;
grantUriPermissions = orig.grantUriPermissions;
uriPermissionPatterns = orig.uriPermissionPatterns;
+ pathPermissions = orig.pathPermissions;
multiprocess = orig.multiprocess;
initOrder = orig.initOrder;
isSyncable = orig.isSyncable;
@@ -94,6 +104,7 @@ public final class ProviderInfo extends ComponentInfo
out.writeString(writePermission);
out.writeInt(grantUriPermissions ? 1 : 0);
out.writeTypedArray(uriPermissionPatterns, parcelableFlags);
+ out.writeTypedArray(pathPermissions, parcelableFlags);
out.writeInt(multiprocess ? 1 : 0);
out.writeInt(initOrder);
out.writeInt(isSyncable ? 1 : 0);
@@ -122,6 +133,7 @@ public final class ProviderInfo extends ComponentInfo
writePermission = in.readString();
grantUriPermissions = in.readInt() != 0;
uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR);
+ pathPermissions = in.createTypedArray(PathPermission.CREATOR);
multiprocess = in.readInt() != 0;
initOrder = in.readInt();
isSyncable = in.readInt() != 0;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index f90cbff..ed1e4ff 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -606,6 +606,7 @@ public class TextToSpeech {
result = mITts.setLanguage(mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1],
mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1],
mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] );
+ } catch (RemoteException e) {
// TTS died; restart it.
mStarted = false;
initTts();
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 77a8a72..57b5aa6 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -55,6 +55,7 @@ public:
~JNICameraContext() { release(); }
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
+ virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
void release();
@@ -188,6 +189,12 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
}
}
+void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
+{
+ // TODO: plumb up to Java. For now, just drop the timestamp
+ postData(msgType, dataPtr);
+}
+
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 599360f..23967f4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -995,6 +995,29 @@
android:description="@string/permdesc_changeBackgroundDataSetting"
android:label="@string/permlab_changeBackgroundDataSetting" />
+ <!-- This permission can be used on content providers to allow the global
+ search system to access their data. Typically it used when the
+ provider has some permissions protecting it (which global search
+ would not be expected to hold), and added as a read-only permission
+ to the path in the provider where global search queries are
+ performed. This permission can not be held by regular applications;
+ it is used by applications to protect themselves from everyone else
+ besides global search. -->
+ <permission android:name="android.permission.GLOBAL_SEARCH"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signatureOrSystem" />
+
+ <!-- Internal permission protecting access to the global search
+ system: ensures that only the system can access the provider
+ to perform queries (since this otherwise provides unrestricted
+ access to a variety of content providers), and to write the
+ search statistics (to keep applications from gaming the source
+ ranking).
+ @hide -->
+ <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL"
+ android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+ android:protectionLevel="signature" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 7571e24..12a76ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -953,6 +953,20 @@
<attr name="pathPattern" format="string" />
</declare-styleable>
+ <!-- Attributes that can be supplied in an AndroidManifest.xml
+ <code>path-permission</code> tag, a child of the
+ {@link #AndroidManifestProvider provider} tag, describing a permission
+ that allows access to a specific path in the provider. This tag can be
+ specified multiple time to supply multiple paths. -->
+ <declare-styleable name="AndroidManifestPathPermission" parent="AndroidManifestProvider">
+ <attr name="path" />
+ <attr name="pathPrefix" />
+ <attr name="pathPattern" />
+ <attr name="permission" />
+ <attr name="readPermission" />
+ <attr name="writePermission" />
+ </declare-styleable>
+
<!-- The <code>service</code> tag declares a
{@link android.app.Service} class that is available
as part of the package's application components, implementing
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index e3544ab..afb07b5 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -18,6 +18,7 @@
#ifndef ANDROID_HARDWARE_CAMERA_H
#define ANDROID_HARDWARE_CAMERA_H
+#include <utils/Timers.h>
#include <ui/ICameraClient.h>
namespace android {
@@ -94,6 +95,7 @@ class CameraListener: virtual public RefBase
public:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+ virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0;
};
class Camera : public BnCameraClient, public IBinder::DeathRecipient
@@ -155,6 +157,7 @@ public:
// ICameraClient interface
virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr);
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
sp<ICamera> remote();
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index 73036f0..822b4a8 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -28,7 +28,7 @@ namespace android {
typedef void (*preview_callback)(const sp<IMemory>& mem, void* user);
/** Callback for startRecord() */
-typedef void (*recording_callback)(const sp<IMemory>& mem, void* user);
+typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
/** Callback for takePicture() */
typedef void (*shutter_callback)(void* user);
diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h
index c4bdd07..1001c71 100644
--- a/include/ui/ICameraClient.h
+++ b/include/ui/ICameraClient.h
@@ -21,6 +21,7 @@
#include <utils/IInterface.h>
#include <utils/Parcel.h>
#include <utils/IMemory.h>
+#include <utils/Timers.h>
namespace android {
@@ -31,7 +32,7 @@ public:
virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
virtual void dataCallback(int32_t msgType, const sp<IMemory>& data) = 0;
-
+ virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 975594f..5015379 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -310,6 +310,19 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
}
}
+// callback from camera service when timestamped frame is ready
+void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr)
+{
+ sp<CameraListener> listener;
+ {
+ Mutex::Autolock _l(mLock);
+ listener = mListener;
+ }
+ if (listener != NULL) {
+ listener->postDataTimestamp(timestamp, msgType, dataPtr);
+ }
+}
+
void Camera::binderDied(const wp<IBinder>& who) {
LOGW("ICamera died");
notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0);
diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp
index c6cf75c..59a6cf2 100644
--- a/libs/ui/ICameraClient.cpp
+++ b/libs/ui/ICameraClient.cpp
@@ -27,6 +27,7 @@ namespace android {
enum {
NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION,
DATA_CALLBACK,
+ DATA_CALLBACK_TIMESTAMP,
};
class BpCameraClient: public BpInterface<ICameraClient>
@@ -60,6 +61,17 @@ public:
remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
}
+ // generic data callback from camera service to app with image data
+ void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData)
+ {
+ LOGV("dataCallback");
+ Parcel data, reply;
+ data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
+ data.writeInt64(timestamp);
+ data.writeInt32(msgType);
+ data.writeStrongBinder(imageData->asBinder());
+ remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient");
@@ -86,13 +98,22 @@ status_t BnCameraClient::onTransact(
return NO_ERROR;
} break;
case DATA_CALLBACK: {
- LOGV("RAW_CALLBACK");
+ LOGV("DATA_CALLBACK");
CHECK_INTERFACE(ICameraClient, data, reply);
int32_t msgType = data.readInt32();
sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
dataCallback(msgType, imageData);
return NO_ERROR;
} break;
+ case DATA_CALLBACK_TIMESTAMP: {
+ LOGV("DATA_CALLBACK_TIMESTAMP");
+ CHECK_INTERFACE(ICameraClient, data, reply);
+ nsecs_t timestamp = data.readInt64();
+ int32_t msgType = data.readInt32();
+ sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder());
+ dataCallbackTimestamp(timestamp, msgType, imageData);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 854138c..190d3e6 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -88,7 +88,8 @@ class NotificationManagerService extends INotificationManager.Stub
private NotificationRecord mSoundNotification;
private AsyncPlayer mSound;
- private int mDisabledNotifications;
+ private boolean mSystemReady;
+ private int mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
private NotificationRecord mVibrateNotification;
private Vibrator mVibrator = new Vibrator();
@@ -377,6 +378,11 @@ class NotificationManagerService extends INotificationManager.Stub
mSettingsObserver.observe();
}
+ void systemReady() {
+ // no beeping until we're basically done booting
+ mSystemReady = true;
+ }
+
// Toasts
// ============================================================================
public void enqueueToast(String pkg, ITransientNotification callback, int duration)
@@ -637,7 +643,7 @@ class NotificationManagerService extends INotificationManager.Stub
}
}
- sendAccessibilityEventTypeNotificationChangedDoCheck(notification, pkg);
+ sendAccessibilityEvent(notification, pkg);
} else {
if (old != null && old.statusBarKey != null) {
@@ -654,7 +660,8 @@ class NotificationManagerService extends INotificationManager.Stub
// If we're not supposed to beep, vibrate, etc. then don't.
if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0)
&& (!(old != null
- && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))) {
+ && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
+ && mSystemReady) {
// sound
final boolean useDefaultSound =
(notification.defaults & Notification.DEFAULT_SOUND) != 0;
@@ -721,8 +728,7 @@ class NotificationManagerService extends INotificationManager.Stub
idOut[0] = id;
}
- private void sendAccessibilityEventTypeNotificationChangedDoCheck(Notification notification,
- CharSequence packageName) {
+ private void sendAccessibilityEvent(Notification notification, CharSequence packageName) {
AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
if (!manager.isEnabled()) {
return;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3e4d5f9..b038a64 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -190,6 +190,7 @@ class ServerThread extends Thread {
StatusBarService statusBar = null;
InputMethodManagerService imm = null;
AppWidgetService appWidget = null;
+ NotificationManagerService notification = null;
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
@@ -240,8 +241,8 @@ class ServerThread extends Thread {
try {
Log.i(TAG, "Starting Notification Manager.");
- ServiceManager.addService(Context.NOTIFICATION_SERVICE,
- new NotificationManagerService(context, statusBar, hardware));
+ notification = new NotificationManagerService(context, statusBar, hardware);
+ ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification);
} catch (Throwable e) {
Log.e(TAG, "Failure starting Notification Manager", e);
}
@@ -348,6 +349,11 @@ class ServerThread extends Thread {
// It is now time to start up the app processes...
boolean safeMode = wm.detectSafeMode();
+
+ if (notification != null) {
+ notification.systemReady();
+ }
+
if (statusBar != null) {
statusBar.systemReady();
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2fe4dd4..aad542a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -56,6 +56,7 @@ import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -7072,6 +7073,27 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
== PackageManager.PERMISSION_GRANTED) {
return null;
}
+
+ PathPermission[] pps = cpi.pathPermissions;
+ if (pps != null) {
+ int i = pps.length;
+ while (i > 0) {
+ i--;
+ PathPermission pp = pps[i];
+ if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid,
+ cpi.exported ? -1 : cpi.applicationInfo.uid)
+ == PackageManager.PERMISSION_GRANTED
+ && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) {
+ return null;
+ }
+ if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid,
+ cpi.exported ? -1 : cpi.applicationInfo.uid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+ }
+ }
+
String msg = "Permission Denial: opening provider " + cpi.name
+ " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+ ", uid=" + callingUid + ") requires "