Merge "Clip TouchFeedbackDrawable effect to receiver Outline"
diff --git a/Android.mk b/Android.mk
index c2910fd..be7e055 100644
--- a/Android.mk
+++ b/Android.mk
@@ -155,6 +155,7 @@
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
+ core/java/android/net/INetworkScoreService.aidl \
core/java/android/net/INetworkStatsService.aidl \
core/java/android/net/INetworkStatsSession.aidl \
core/java/android/net/nsd/INsdManager.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index ffdac4e..c6f6a62 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -189,6 +189,7 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index 3573e6d..ef6aed7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3175,6 +3175,7 @@
method public void finishActivity(int);
method public void finishActivityFromChild(android.app.Activity, int);
method public void finishAffinity();
+ method public void finishAndRemoveTask();
method public void finishFromChild(android.app.Activity);
method public void finishWithTransition();
method public android.app.ActionBar getActionBar();
@@ -6927,6 +6928,7 @@
field public static final java.lang.String ACTION_PASTE = "android.intent.action.PASTE";
field public static final java.lang.String ACTION_PICK = "android.intent.action.PICK";
field public static final java.lang.String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
+ field public static final java.lang.String ACTION_PICK_DIRECTORY = "android.intent.action.PICK_DIRECTORY";
field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
@@ -7075,6 +7077,7 @@
field public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 16; // 0x10
field public static final int FLAG_FROM_BACKGROUND = 4; // 0x4
field public static final int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 64; // 0x40
+ field public static final int FLAG_GRANT_PREFIX_URI_PERMISSION = 128; // 0x80
field public static final int FLAG_GRANT_READ_URI_PERMISSION = 1; // 0x1
field public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 2; // 0x2
field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20
@@ -16811,11 +16814,24 @@
package android.nfc.cardemulation {
+ public final class AidGroup implements android.os.Parcelable {
+ ctor public AidGroup(java.util.ArrayList<java.lang.String>, java.lang.String);
+ method public int describeContents();
+ method public java.util.ArrayList<java.lang.String> getAids();
+ method public java.lang.String getCategory();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final int MAX_NUM_AIDS = 256; // 0x100
+ }
+
public final class CardEmulation {
+ method public android.nfc.cardemulation.AidGroup getAidGroupForService(android.content.ComponentName, java.lang.String);
method public static synchronized android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
method public int getSelectionModeForCategory(java.lang.String);
method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String);
method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
+ method public boolean registerAidGroupForService(android.content.ComponentName, android.nfc.cardemulation.AidGroup);
+ method public boolean removeAidGroupForService(android.content.ComponentName, java.lang.String);
field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final java.lang.String CATEGORY_OTHER = "other";
field public static final java.lang.String CATEGORY_PAYMENT = "payment";
@@ -19254,11 +19270,12 @@
field public static final int L = 10000; // 0x2710
}
- public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
+ public final class Bundle extends android.os.CommonBundle {
ctor public Bundle();
ctor public Bundle(java.lang.ClassLoader);
ctor public Bundle(int);
ctor public Bundle(android.os.Bundle);
+ ctor public Bundle(android.os.PersistableBundle);
method public void clear();
method public java.lang.Object clone();
method public boolean containsKey(java.lang.String);
@@ -19296,6 +19313,7 @@
method public T getParcelable(java.lang.String);
method public android.os.Parcelable[] getParcelableArray(java.lang.String);
method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+ method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
method public java.io.Serializable getSerializable(java.lang.String);
method public short getShort(java.lang.String);
method public short getShort(java.lang.String, short);
@@ -19309,6 +19327,7 @@
method public boolean isEmpty();
method public java.util.Set<java.lang.String> keySet();
method public void putAll(android.os.Bundle);
+ method public void putAll(android.os.PersistableBundle);
method public void putBinder(java.lang.String, android.os.IBinder);
method public void putBoolean(java.lang.String, boolean);
method public void putBooleanArray(java.lang.String, boolean[]);
@@ -19332,6 +19351,7 @@
method public void putParcelable(java.lang.String, android.os.Parcelable);
method public void putParcelableArray(java.lang.String, android.os.Parcelable[]);
method public void putParcelableArrayList(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>);
+ method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
method public void putSerializable(java.lang.String, java.io.Serializable);
method public void putShort(java.lang.String, short);
method public void putShortArray(java.lang.String, short[]);
@@ -19360,6 +19380,9 @@
method public abstract void onCancel();
}
+ abstract class CommonBundle implements java.lang.Cloneable android.os.Parcelable {
+ }
+
public class ConditionVariable {
ctor public ConditionVariable();
ctor public ConditionVariable(boolean);
@@ -19786,6 +19809,8 @@
method public final void readMap(java.util.Map, java.lang.ClassLoader);
method public final T readParcelable(java.lang.ClassLoader);
method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+ method public final android.os.PersistableBundle readPersistableBundle();
+ method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
method public final java.io.Serializable readSerializable();
method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
method public final android.util.SparseBooleanArray readSparseBooleanArray();
@@ -19826,6 +19851,7 @@
method public final void writeNoException();
method public final void writeParcelable(android.os.Parcelable, int);
method public final void writeParcelableArray(T[], int);
+ method public final void writePersistableBundle(android.os.PersistableBundle);
method public final void writeSerializable(java.io.Serializable);
method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
@@ -19936,6 +19962,51 @@
field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
}
+ public final class PersistableBundle extends android.os.CommonBundle {
+ ctor public PersistableBundle();
+ ctor public PersistableBundle(java.lang.ClassLoader);
+ ctor public PersistableBundle(int);
+ ctor public PersistableBundle(android.os.PersistableBundle);
+ method public void clear();
+ method public java.lang.Object clone();
+ method public boolean containsKey(java.lang.String);
+ method public int describeContents();
+ method public java.lang.Object get(java.lang.String);
+ method public java.lang.ClassLoader getClassLoader();
+ method public double getDouble(java.lang.String);
+ method public double getDouble(java.lang.String, double);
+ method public double[] getDoubleArray(java.lang.String);
+ method public int getInt(java.lang.String);
+ method public int getInt(java.lang.String, int);
+ method public int[] getIntArray(java.lang.String);
+ method public long getLong(java.lang.String);
+ method public long getLong(java.lang.String, long);
+ method public long[] getLongArray(java.lang.String);
+ method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+ method public java.lang.String getString(java.lang.String);
+ method public java.lang.String getString(java.lang.String, java.lang.String);
+ method public java.lang.String[] getStringArray(java.lang.String);
+ method public boolean isEmpty();
+ method public java.util.Set<java.lang.String> keySet();
+ method public void putAll(android.os.PersistableBundle);
+ method public void putDouble(java.lang.String, double);
+ method public void putDoubleArray(java.lang.String, double[]);
+ method public void putInt(java.lang.String, int);
+ method public void putIntArray(java.lang.String, int[]);
+ method public void putLong(java.lang.String, long);
+ method public void putLongArray(java.lang.String, long[]);
+ method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
+ method public void putString(java.lang.String, java.lang.String);
+ method public void putStringArray(java.lang.String, java.lang.String[]);
+ method public void readFromParcel(android.os.Parcel);
+ method public void remove(java.lang.String);
+ method public void setClassLoader(java.lang.ClassLoader);
+ method public int size();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final android.os.PersistableBundle EMPTY;
+ }
+
public final class PowerManager {
method public void goToSleep(long);
method public boolean isInteractive();
@@ -22479,16 +22550,21 @@
public final class DocumentsContract {
method public static android.net.Uri buildChildDocumentsUri(java.lang.String, java.lang.String);
+ method public static android.net.Uri buildChildDocumentsViaUri(android.net.Uri, java.lang.String);
method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String);
+ method public static android.net.Uri buildDocumentViaUri(android.net.Uri, java.lang.String);
method public static android.net.Uri buildRecentDocumentsUri(java.lang.String, java.lang.String);
method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
method public static android.net.Uri buildRootsUri(java.lang.String);
method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
+ method public static android.net.Uri buildViaUri(java.lang.String, java.lang.String);
+ method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
method public static java.lang.String getDocumentId(android.net.Uri);
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
method public static java.lang.String getRootId(android.net.Uri);
method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
+ method public static java.lang.String getViaDocumentId(android.net.Uri);
method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
field public static final java.lang.String EXTRA_ERROR = "error";
field public static final java.lang.String EXTRA_INFO = "info";
@@ -22525,6 +22601,7 @@
field public static final java.lang.String COLUMN_TITLE = "title";
field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
+ field public static final int FLAG_SUPPORTS_DIR_SELECTION = 16; // 0x10
field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4
field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8
}
@@ -22537,6 +22614,9 @@
method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
method public final java.lang.String getType(android.net.Uri);
method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+ method public boolean isChildDocument(java.lang.String, java.lang.String);
+ method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+ method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public abstract android.os.ParcelFileDescriptor openDocument(java.lang.String, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public android.content.res.AssetFileDescriptor openDocumentThumbnail(java.lang.String, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -22549,6 +22629,7 @@
method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+ method public final void revokeDocumentPermission(java.lang.String);
method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
@@ -27974,7 +28055,6 @@
public static final class TvInputManager.Session {
method public void release();
- method public void setSurface(android.view.Surface);
method public void setVolume(float);
method public void tune(android.net.Uri);
}
@@ -27996,12 +28076,22 @@
field public static final java.lang.String SERVICE_INTERFACE = "android.tv.TvInputService";
}
- public static abstract class TvInputService.TvInputSessionImpl {
+ public abstract class TvInputService.TvInputSessionImpl {
ctor public TvInputService.TvInputSessionImpl();
+ method public android.view.View onCreateOverlayView();
method public abstract void onRelease();
method public abstract boolean onSetSurface(android.view.Surface);
method public abstract void onSetVolume(float);
method public abstract boolean onTune(android.net.Uri);
+ method public void setOverlayViewEnabled(boolean);
+ }
+
+ public class TvView extends android.view.SurfaceView {
+ ctor public TvView(android.content.Context);
+ ctor public TvView(android.content.Context, android.util.AttributeSet);
+ ctor public TvView(android.content.Context, android.util.AttributeSet, int);
+ method public void bindTvInput(android.content.ComponentName, android.tv.TvInputManager.SessionCreateCallback);
+ method public void unbindTvInput();
}
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 92cb52c..7df55a5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -240,6 +240,7 @@
" (to embed a comma into a string escape it using \"\\,\")\n" +
" [-n <COMPONENT>] [-f <FLAGS>]\n" +
" [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+ " [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" +
" [--debug-log-resolution] [--exclude-stopped-packages]\n" +
" [--include-stopped-packages]\n" +
" [--activity-brought-to-front] [--activity-clear-top]\n" +
@@ -455,6 +456,10 @@
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else if (opt.equals("--grant-write-uri-permission")) {
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ } else if (opt.equals("--grant-persistable-uri-permission")) {
+ intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+ } else if (opt.equals("--grant-prefix-uri-permission")) {
+ intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
} else if (opt.equals("--exclude-stopped-packages")) {
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
} else if (opt.equals("--include-stopped-packages")) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a5a06e3..599a608 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4314,11 +4314,10 @@
}
/**
- * Call this when your activity is done and should be closed. The
- * ActivityResult is propagated back to whoever launched you via
- * onActivityResult().
+ * Finishes the current activity and specifies whether to remove the task associated with this
+ * activity.
*/
- public void finish() {
+ private void finish(boolean finishTask) {
if (mParent == null) {
int resultCode;
Intent resultData;
@@ -4332,7 +4331,7 @@
resultData.prepareToLeaveProcess();
}
if (ActivityManagerNative.getDefault()
- .finishActivity(mToken, resultCode, resultData)) {
+ .finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
@@ -4344,6 +4343,15 @@
}
/**
+ * Call this when your activity is done and should be closed. The
+ * ActivityResult is propagated back to whoever launched you via
+ * onActivityResult().
+ */
+ public void finish() {
+ finish(false);
+ }
+
+ /**
* Finish this activity as well as all activities immediately below it
* in the current task that have the same affinity. This is typically
* used when an application can be launched on to another task (such as
@@ -4442,6 +4450,14 @@
}
/**
+ * Call this when your activity is done and should be closed and the task should be completely
+ * removed as a part of finishing the Activity.
+ */
+ public void finishAndRemoveTask() {
+ finish(true);
+ }
+
+ /**
* Called when an activity you launched exits, giving you the requestCode
* you started it with, the resultCode it returned, and any additional
* data from it. The <var>resultCode</var> will be
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 44c74d8..10831f2 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -263,7 +263,8 @@
if (data.readInt() != 0) {
resultData = Intent.CREATOR.createFromParcel(data);
}
- boolean res = finishActivity(token, resultCode, resultData);
+ boolean finishTask = (data.readInt() != 0);
+ boolean res = finishActivity(token, resultCode, resultData, finishTask);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2342,7 +2343,7 @@
data.recycle();
return result != 0;
}
- public boolean finishActivity(IBinder token, int resultCode, Intent resultData)
+ public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -2355,6 +2356,7 @@
} else {
data.writeInt(0);
}
+ data.writeInt(finishTask ? 1 : 0);
mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 965f815..88eae7f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2363,7 +2363,7 @@
// manager to stop us.
try {
ActivityManagerNative.getDefault()
- .finishActivity(r.token, Activity.RESULT_CANCELED, null);
+ .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
// Ignore
}
@@ -2984,7 +2984,7 @@
// just end this activity.
try {
ActivityManagerNative.getDefault()
- .finishActivity(token, Activity.RESULT_CANCELED, null);
+ .finishActivity(token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
}
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 51cb12a..edf21dd 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -33,17 +33,20 @@
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
-import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import dalvik.system.CloseGuard;
+
+import java.lang.ref.WeakReference;
/** @hide */
public class ActivityView extends ViewGroup {
- private final String TAG = "ActivityView";
- private final boolean DEBUG = false;
+ private static final String TAG = "ActivityView";
+ private static final boolean DEBUG = false;
+ DisplayMetrics mMetrics;
private final TextureView mTextureView;
- private IActivityContainer mActivityContainer;
+ private ActivityContainerWrapper mActivityContainer;
private Activity mActivity;
private int mWidth;
private int mHeight;
@@ -75,9 +78,23 @@
throw new IllegalStateException("The ActivityView's Context is not an Activity.");
}
+ try {
+ mActivityContainer = new ActivityContainerWrapper(
+ ActivityManagerNative.getDefault().createActivityContainer(
+ mActivity.getActivityToken(), new ActivityContainerCallback(this)));
+ } catch (RemoteException e) {
+ throw new RuntimeException("ActivityView: Unable to create ActivityContainer. "
+ + e);
+ }
+
mTextureView = new TextureView(context);
mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
addView(mTextureView);
+
+ WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
+ mMetrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getMetrics(mMetrics);
+
if (DEBUG) Log.v(TAG, "ctor()");
}
@@ -86,57 +103,8 @@
mTextureView.layout(0, 0, r - l, b - t);
}
- @Override
- protected void onAttachedToWindow() {
- if (DEBUG) Log.v(TAG, "onAttachedToWindow()");
- super.onAttachedToWindow();
- try {
- final IBinder token = mActivity.getActivityToken();
- mActivityContainer = ActivityManagerNative.getDefault().createActivityContainer(token,
- new ActivityContainerCallback());
- } catch (RemoteException e) {
- throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
- + e);
- }
-
- attachToSurfaceWhenReady();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer);
- super.onDetachedFromWindow();
- if (mActivityContainer != null) {
- detach();
- try {
- ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer);
- } catch (RemoteException e) {
- }
- mActivityContainer = null;
- }
- }
-
- @Override
- protected void onWindowVisibilityChanged(int visibility) {
- if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility);
- super.onWindowVisibilityChanged(visibility);
- switch (visibility) {
- case View.VISIBLE:
- attachToSurfaceWhenReady();
- break;
- case View.INVISIBLE:
- break;
- case View.GONE:
- break;
- }
- }
-
private boolean injectInputEvent(InputEvent event) {
- try {
- return mActivityContainer != null && mActivityContainer.injectEvent(event);
- } catch (RemoteException e) {
- return false;
- }
+ return mActivityContainer != null && mActivityContainer.injectEvent(event);
}
@Override
@@ -154,40 +122,45 @@
return super.onGenericMotionEvent(event);
}
+ @Override
+ public void onAttachedToWindow() {
+ if (DEBUG) Log.v(TAG, "onAttachedToWindow(): mActivityContainer=" + mActivityContainer +
+ " mSurface=" + mSurface);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer +
+ " mSurface=" + mSurface);
+ }
+
public boolean isAttachedToDisplay() {
return mSurface != null;
}
public void startActivity(Intent intent) {
+ if (mActivityContainer == null) {
+ throw new IllegalStateException("Attempt to call startActivity after release");
+ }
if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
(isAttachedToDisplay() ? "" : "not") + " attached");
if (mSurface != null) {
- try {
- mActivityContainer.startActivity(intent);
- } catch (RemoteException e) {
- throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
- }
+ mActivityContainer.startActivity(intent);
} else {
mQueuedIntent = intent;
mQueuedPendingIntent = null;
}
}
- private void startActivityIntentSender(IIntentSender iIntentSender) {
- try {
- mActivityContainer.startActivityIntentSender(iIntentSender);
- } catch (RemoteException e) {
- throw new IllegalStateException(
- "ActivityView: Unable to startActivity from IntentSender. " + e);
- }
- }
-
public void startActivity(IntentSender intentSender) {
+ if (mActivityContainer == null) {
+ throw new IllegalStateException("Attempt to call startActivity after release");
+ }
if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
(isAttachedToDisplay() ? "" : "not") + " attached");
final IIntentSender iIntentSender = intentSender.getTarget();
if (mSurface != null) {
- startActivityIntentSender(iIntentSender);
+ mActivityContainer.startActivityIntentSender(iIntentSender);
} else {
mQueuedPendingIntent = iIntentSender;
mQueuedIntent = null;
@@ -195,84 +168,102 @@
}
public void startActivity(PendingIntent pendingIntent) {
+ if (mActivityContainer == null) {
+ throw new IllegalStateException("Attempt to call startActivity after release");
+ }
if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
+ (isAttachedToDisplay() ? "" : "not") + " attached");
final IIntentSender iIntentSender = pendingIntent.getTarget();
if (mSurface != null) {
- startActivityIntentSender(iIntentSender);
+ mActivityContainer.startActivityIntentSender(iIntentSender);
} else {
mQueuedPendingIntent = iIntentSender;
mQueuedIntent = null;
}
}
+ public void release() {
+ if (DEBUG) Log.v(TAG, "release() mActivityContainer=" + mActivityContainer +
+ " mSurface=" + mSurface);
+ if (mActivityContainer == null) {
+ Log.e(TAG, "Duplicate call to release");
+ return;
+ }
+ mActivityContainer.release();
+ mActivityContainer = null;
+
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+
+ mTextureView.setSurfaceTextureListener(null);
+ }
+
private void attachToSurfaceWhenReady() {
final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
- if (mActivityContainer == null || surfaceTexture == null || mSurface != null) {
+ if (surfaceTexture == null || mSurface != null) {
// Either not ready to attach, or already attached.
return;
}
- WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics metrics = new DisplayMetrics();
- wm.getDefaultDisplay().getMetrics(metrics);
-
mSurface = new Surface(surfaceTexture);
try {
- mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi);
+ mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
} catch (RemoteException e) {
mSurface.release();
mSurface = null;
- throw new IllegalStateException(
- "ActivityView: Unable to create ActivityContainer. " + e);
+ throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e);
}
if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
mQueuedPendingIntent != null ? "" : "no") + " queued intent");
if (mQueuedIntent != null) {
- startActivity(mQueuedIntent);
+ mActivityContainer.startActivity(mQueuedIntent);
mQueuedIntent = null;
} else if (mQueuedPendingIntent != null) {
- startActivityIntentSender(mQueuedPendingIntent);
+ mActivityContainer.startActivityIntentSender(mQueuedPendingIntent);
mQueuedPendingIntent = null;
}
}
- private void detach() {
- if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay());
- if (mSurface != null) {
- try {
- mActivityContainer.detachFromDisplay();
- } catch (RemoteException e) {
- }
- mSurface.release();
- mSurface = null;
- }
- }
-
private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
int height) {
+ if (mActivityContainer == null) {
+ return;
+ }
if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
+ height);
mWidth = width;
mHeight = height;
- if (mActivityContainer != null) {
- attachToSurfaceWhenReady();
- }
+ attachToSurfaceWhenReady();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
int height) {
+ if (mActivityContainer == null) {
+ return;
+ }
if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ if (mActivityContainer == null) {
+ return true;
+ }
if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
- detach();
+ mSurface.release();
+ mSurface = null;
+ try {
+ mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to set surface of ActivityContainer. " + e);
+ }
return true;
}
@@ -283,13 +274,95 @@
}
- private class ActivityContainerCallback extends IActivityContainerCallback.Stub {
+ private static class ActivityContainerCallback extends IActivityContainerCallback.Stub {
+ private final WeakReference<ActivityView> mActivityViewWeakReference;
+
+ ActivityContainerCallback(ActivityView activityView) {
+ mActivityViewWeakReference = new WeakReference<ActivityView>(activityView);
+ }
+
@Override
public void setVisible(IBinder container, boolean visible) {
- if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible);
- if (visible) {
- } else {
+ if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible +
+ " ActivityView=" + mActivityViewWeakReference.get());
+ }
+ }
+
+ private static class ActivityContainerWrapper {
+ private final IActivityContainer mIActivityContainer;
+ private final CloseGuard mGuard = CloseGuard.get();
+
+ ActivityContainerWrapper(IActivityContainer container) {
+ mIActivityContainer = container;
+ mGuard.open("release");
+ }
+
+ void attachToDisplay(int displayId) {
+ try {
+ mIActivityContainer.attachToDisplay(displayId);
+ } catch (RemoteException e) {
}
}
+
+ void setSurface(Surface surface, int width, int height, int density)
+ throws RemoteException {
+ mIActivityContainer.setSurface(surface, width, height, density);
+ }
+
+ int startActivity(Intent intent) {
+ try {
+ return mIActivityContainer.startActivity(intent);
+ } catch (RemoteException e) {
+ throw new RuntimeException("ActivityView: Unable to startActivity. " + e);
+ }
+ }
+
+ int startActivityIntentSender(IIntentSender intentSender) {
+ try {
+ return mIActivityContainer.startActivityIntentSender(intentSender);
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to startActivity from IntentSender. " + e);
+ }
+ }
+
+ int getDisplayId() {
+ try {
+ return mIActivityContainer.getDisplayId();
+ } catch (RemoteException e) {
+ return -1;
+ }
+ }
+
+ boolean injectEvent(InputEvent event) {
+ try {
+ return mIActivityContainer.injectEvent(event);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ void release() {
+ if (DEBUG) Log.v(TAG, "ActivityContainerWrapper: release called");
+ try {
+ mIActivityContainer.release();
+ mGuard.close();
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (DEBUG) Log.v(TAG, "ActivityContainerWrapper: finalize called");
+ try {
+ if (mGuard != null) {
+ mGuard.warnIfOpen();
+ release();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f1ce54a..fe532bf 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1865,17 +1865,26 @@
}
private String uriModeFlagToString(int uriModeFlags) {
- switch (uriModeFlags) {
- case Intent.FLAG_GRANT_READ_URI_PERMISSION |
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
- return "read and write";
- case Intent.FLAG_GRANT_READ_URI_PERMISSION:
- return "read";
- case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
- return "write";
+ StringBuilder builder = new StringBuilder();
+ if ((uriModeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ builder.append("read and ");
}
- throw new IllegalArgumentException(
- "Unknown permission mode flags: " + uriModeFlags);
+ if ((uriModeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ builder.append("write and ");
+ }
+ if ((uriModeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) {
+ builder.append("persistable and ");
+ }
+ if ((uriModeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) {
+ builder.append("prefix and ");
+ }
+
+ if (builder.length() > 5) {
+ builder.setLength(builder.length() - 5);
+ return builder.toString();
+ } else {
+ throw new IllegalArgumentException("Unknown permission mode flags: " + uriModeFlags);
+ }
}
private void enforceForUri(
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index 5b80e06..cc3b10c 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -26,10 +26,10 @@
/** @hide */
interface IActivityContainer {
void attachToDisplay(int displayId);
- void attachToSurface(in Surface surface, int width, int height, int density);
- void detachFromDisplay();
+ void setSurface(in Surface surface, int width, int height, int density);
int startActivity(in Intent intent);
int startActivityIntentSender(in IIntentSender intentSender);
int getDisplayId();
boolean injectEvent(in InputEvent event);
+ void release();
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index bfbd339..52003f1 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -79,7 +79,7 @@
int flagsMask, int flagsValues, Bundle options) throws RemoteException;
public boolean startNextMatchingActivity(IBinder callingActivity,
Intent intent, Bundle options) throws RemoteException;
- public boolean finishActivity(IBinder token, int code, Intent data)
+ public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask)
throws RemoteException;
public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
public boolean finishActivityAffinity(IBinder token) throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bb6eeda..8681f5c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -23,6 +23,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.service.notification.INotificationListener;
+import android.service.notification.ZenModeConfig;
/** {@hide} */
interface INotificationManager
@@ -49,4 +50,7 @@
StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
String[] getActiveNotificationKeysFromListener(in INotificationListener token);
+
+ ZenModeConfig getZenModeConfig();
+ boolean setZenModeConfig(in ZenModeConfig config);
}
\ No newline at end of file
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index a6a04d1..5cf61a8 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -41,8 +41,6 @@
@Deprecated
public static final int DISABLE_NOTIFICATION_TICKER
= View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
- public static final int DISABLE_PRIVATE_NOTIFICATIONS
- = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;
public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME;
public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f3c803d..5b41394 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1641,7 +1641,7 @@
*
* @see #getPersistedUriPermissions()
*/
- public void takePersistableUriPermission(Uri uri, int modeFlags) {
+ public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
ActivityManagerNative.getDefault().takePersistableUriPermission(uri, modeFlags);
} catch (RemoteException e) {
@@ -1656,7 +1656,7 @@
*
* @see #getPersistedUriPermissions()
*/
- public void releasePersistableUriPermission(Uri uri, int modeFlags) {
+ public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
try {
ActivityManagerNative.getDefault().releasePersistableUriPermission(uri, modeFlags);
} catch (RemoteException e) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 906484a..cbb6cf5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2791,9 +2791,13 @@
* @param uri The Uri you would like to grant access to.
* @param modeFlags The desired access modes. Any combination of
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
- * Intent.FLAG_GRANT_READ_URI_PERMISSION} or
+ * Intent.FLAG_GRANT_READ_URI_PERMISSION},
* {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
- * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
+ * Intent.FLAG_GRANT_WRITE_URI_PERMISSION},
+ * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ * Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION}, or
+ * {@link Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
+ * Intent.FLAG_GRANT_PREFIX_URI_PERMISSION}.
*
* @see #revokeUriPermission
*/
@@ -2806,7 +2810,8 @@
* Uri will match all previously granted Uris that are the same or a
* sub-path of the given Uri. That is, revoking "content://foo/target" will
* revoke both "content://foo/target" and "content://foo/target/sub", but not
- * "content://foo".
+ * "content://foo". It will not remove any prefix grants that exist at a
+ * higher level.
*
* @param uri The Uri you would like to revoke access to.
* @param modeFlags The desired access modes. Any combination of
@@ -2817,7 +2822,7 @@
*
* @see #grantUriPermission
*/
- public abstract void revokeUriPermission(Uri uri, @Intent.GrantUriMode int modeFlags);
+ public abstract void revokeUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags);
/**
* Determine whether a particular process and user ID has been granted
@@ -2841,7 +2846,7 @@
* @see #checkCallingUriPermission
*/
public abstract int checkUriPermission(Uri uri, int pid, int uid,
- @Intent.GrantUriMode int modeFlags);
+ @Intent.AccessUriMode int modeFlags);
/**
* Determine whether the calling process and user ID has been
@@ -2864,7 +2869,7 @@
*
* @see #checkUriPermission(Uri, int, int, int)
*/
- public abstract int checkCallingUriPermission(Uri uri, @Intent.GrantUriMode int modeFlags);
+ public abstract int checkCallingUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags);
/**
* Determine whether the calling process of an IPC <em>or you</em> has been granted
@@ -2884,7 +2889,7 @@
* @see #checkCallingUriPermission
*/
public abstract int checkCallingOrSelfUriPermission(Uri uri,
- @Intent.GrantUriMode int modeFlags);
+ @Intent.AccessUriMode int modeFlags);
/**
* Check both a Uri and normal permission. This allows you to perform
@@ -2910,7 +2915,7 @@
*/
public abstract int checkUriPermission(@Nullable Uri uri, @Nullable String readPermission,
@Nullable String writePermission, int pid, int uid,
- @Intent.GrantUriMode int modeFlags);
+ @Intent.AccessUriMode int modeFlags);
/**
* If a particular process and user ID has not been granted
@@ -2932,7 +2937,7 @@
* @see #checkUriPermission(Uri, int, int, int)
*/
public abstract void enforceUriPermission(
- Uri uri, int pid, int uid, @Intent.GrantUriMode int modeFlags, String message);
+ Uri uri, int pid, int uid, @Intent.AccessUriMode int modeFlags, String message);
/**
* If the calling process and user ID has not been granted
@@ -2954,7 +2959,7 @@
* @see #checkCallingUriPermission(Uri, int)
*/
public abstract void enforceCallingUriPermission(
- Uri uri, @Intent.GrantUriMode int modeFlags, String message);
+ Uri uri, @Intent.AccessUriMode int modeFlags, String message);
/**
* If the calling process of an IPC <em>or you</em> has not been
@@ -2973,7 +2978,7 @@
* @see #checkCallingOrSelfUriPermission(Uri, int)
*/
public abstract void enforceCallingOrSelfUriPermission(
- Uri uri, @Intent.GrantUriMode int modeFlags, String message);
+ Uri uri, @Intent.AccessUriMode int modeFlags, String message);
/**
* Enforce both a Uri and normal permission. This allows you to perform
@@ -2998,7 +3003,7 @@
*/
public abstract void enforceUriPermission(
@Nullable Uri uri, @Nullable String readPermission,
- @Nullable String writePermission, int pid, int uid, @Intent.GrantUriMode int modeFlags,
+ @Nullable String writePermission, int pid, int uid, @Intent.AccessUriMode int modeFlags,
@Nullable String message);
/** @hide */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 421956b..c0f04af 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -18,6 +18,7 @@
import android.content.pm.ApplicationInfo;
import android.util.ArraySet;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -864,8 +865,9 @@
}
// Migrate any clip data and flags from target.
- int permFlags = target.getFlags()
- & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
+ int permFlags = target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
+ | FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | FLAG_GRANT_PREFIX_URI_PERMISSION);
if (permFlags != 0) {
ClipData targetClipData = target.getClipData();
if (targetClipData == null && target.getData() != null) {
@@ -2698,9 +2700,11 @@
* take the persistable permissions using
* {@link ContentResolver#takePersistableUriPermission(Uri, int)}.
* <p>
- * Callers can restrict document selection to a specific kind of data, such
- * as photos, by setting one or more MIME types in
- * {@link #EXTRA_MIME_TYPES}.
+ * Callers must indicate the acceptable document MIME types through
+ * {@link #setType(String)}. For example, to select photos, use
+ * {@code image/*}. If multiple disjoint MIME types are acceptable, define
+ * them in {@link #EXTRA_MIME_TYPES} and {@link #setType(String)} to
+ * {@literal *}/*.
* <p>
* If the caller can handle multiple returned items (the user performing
* multiple selection), then you can specify {@link #EXTRA_ALLOW_MULTIPLE}
@@ -2710,9 +2714,10 @@
* returned URIs can be opened with
* {@link ContentResolver#openFileDescriptor(Uri, String)}.
* <p>
- * Output: The URI of the item that was picked. This must be a
- * {@code content://} URI so that any receiver can access it. If multiple
- * documents were selected, they are returned in {@link #getClipData()}.
+ * Output: The URI of the item that was picked, returned in
+ * {@link #getData()}. This must be a {@code content://} URI so that any
+ * receiver can access it. If multiple documents were selected, they are
+ * returned in {@link #getClipData()}.
*
* @see DocumentsContract
* @see #ACTION_CREATE_DOCUMENT
@@ -2754,6 +2759,24 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
+ /**
+ * Activity Action: Allow the user to pick a directory. When invoked, the
+ * system will display the various {@link DocumentsProvider} instances
+ * installed on the device, letting the user navigate through them. Apps can
+ * fully manage documents within the returned directory.
+ * <p>
+ * To gain access to descendant (child, grandchild, etc) documents, use
+ * {@link DocumentsContract#buildDocumentViaUri(Uri, String)} and
+ * {@link DocumentsContract#buildChildDocumentsViaUri(Uri, String)} using
+ * the returned directory URI.
+ * <p>
+ * Output: The URI representing the selected directory.
+ *
+ * @see DocumentsContract
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_PICK_DIRECTORY = "android.intent.action.PICK_DIRECTORY";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
@@ -3332,6 +3355,7 @@
* @see #ACTION_GET_CONTENT
* @see #ACTION_OPEN_DOCUMENT
* @see #ACTION_CREATE_DOCUMENT
+ * @see #ACTION_PICK_DIRECTORY
*/
public static final String EXTRA_LOCAL_ONLY =
"android.intent.extra.LOCAL_ONLY";
@@ -3425,11 +3449,29 @@
// Intent flags (see mFlags variable).
/** @hide */
- @IntDef(flag = true,
- value = {FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION})
+ @IntDef(flag = true, value = {
+ FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION,
+ FLAG_GRANT_PERSISTABLE_URI_PERMISSION, FLAG_GRANT_PREFIX_URI_PERMISSION })
@Retention(RetentionPolicy.SOURCE)
public @interface GrantUriMode {}
+ /** @hide */
+ @IntDef(flag = true, value = {
+ FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AccessUriMode {}
+
+ /**
+ * Test if given mode flags specify an access mode, which must be at least
+ * read and/or write.
+ *
+ * @hide
+ */
+ public static boolean isAccessUriMode(int modeFlags) {
+ return (modeFlags & (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) != 0;
+ }
+
/**
* If set, the recipient of this Intent will be granted permission to
* perform read operations on the URI in the Intent's data and any URIs
@@ -3491,6 +3533,17 @@
public static final int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 0x00000040;
/**
+ * When combined with {@link #FLAG_GRANT_READ_URI_PERMISSION} and/or
+ * {@link #FLAG_GRANT_WRITE_URI_PERMISSION}, the URI permission grant
+ * applies to any URI that is a prefix match against the original granted
+ * URI. (Without this flag, the URI must match exactly for access to be
+ * granted.) Another URI is considered a prefix match only when scheme,
+ * authority, and all path segments defined by the prefix are an exact
+ * match.
+ */
+ public static final int FLAG_GRANT_PREFIX_URI_PERMISSION = 0x00000080;
+
+ /**
* If set, the new activity is not kept in the history stack. As soon as
* the user navigates away from it, the activity is finished. This may also
* be set with the {@link android.R.styleable#AndroidManifestActivity_noHistory
@@ -3810,9 +3863,9 @@
/**
* @hide Flags that can't be changed with PendingIntent.
*/
- public static final int IMMUTABLE_FLAGS =
- FLAG_GRANT_READ_URI_PERMISSION
- | FLAG_GRANT_WRITE_URI_PERMISSION;
+ public static final int IMMUTABLE_FLAGS = FLAG_GRANT_READ_URI_PERMISSION
+ | FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | FLAG_GRANT_PREFIX_URI_PERMISSION;
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
@@ -6350,6 +6403,8 @@
*
* @see #FLAG_GRANT_READ_URI_PERMISSION
* @see #FLAG_GRANT_WRITE_URI_PERMISSION
+ * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ * @see #FLAG_GRANT_PREFIX_URI_PERMISSION
* @see #FLAG_DEBUG_LOG_RESOLUTION
* @see #FLAG_FROM_BACKGROUND
* @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT
@@ -7381,9 +7436,10 @@
// Since we migrated in child, we need to promote ClipData
// and flags to ourselves to grant.
setClipData(target.getClipData());
- addFlags(target.getFlags()
- & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION
- | FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
+ addFlags(target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
+ | FLAG_GRANT_WRITE_URI_PERMISSION
+ | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | FLAG_GRANT_PREFIX_URI_PERMISSION));
return true;
} else {
return false;
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 7328fe3..ee2adac 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -315,6 +315,12 @@
holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null;
if (holder != null) {
mCaptureListenerMap.removeAt(index);
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "remove holder for requestId %d, "
+ + "because lastFrame is %d.",
+ requestId, lastFrameNumber));
+ }
}
if (holder != null) {
@@ -390,6 +396,10 @@
if (listener != null) {
mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
requestList, handler, repeating));
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Listen for request " + requestId + " is null");
+ }
}
long lastFrameNumber = lastFrameNumberRef.getNumber();
@@ -828,7 +838,8 @@
CaptureResultExtras resultExtras) throws RemoteException {
int requestId = resultExtras.getRequestId();
if (DEBUG) {
- Log.d(TAG, "Received result for id " + requestId);
+ Log.v(TAG, "Received result frame " + resultExtras.getFrameNumber() + " for id "
+ + requestId);
}
final CaptureListenerHolder holder;
synchronized (mLock) {
@@ -838,17 +849,26 @@
Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
+ // Update tracker (increment counter) when it's not a partial result.
+ if (!quirkIsPartialResult) {
+ mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false);
+ }
+
// Check if we have a listener for this
if (holder == null) {
if (DEBUG) {
- Log.v(TAG, "holder is null, early return");
+ Log.d(TAG,
+ "holder is null, early return at frame "
+ + resultExtras.getFrameNumber());
}
return;
}
if (isClosed()) {
if (DEBUG) {
- Log.v(TAG, "camera is closed, early return");
+ Log.d(TAG,
+ "camera is closed, early return at frame "
+ + resultExtras.getFrameNumber());
}
return;
}
@@ -891,7 +911,6 @@
// Fire onCaptureSequenceCompleted
if (!quirkIsPartialResult) {
- mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false);
checkAndFireSequenceComplete();
}
}
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
new file mode 100644
index 0000000..a72d9a0
--- /dev/null
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2014, 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.net;
+
+import android.net.ScoredNetwork;
+
+/**
+ * A service for updating network scores from a network scorer application.
+ * @hide
+ */
+interface INetworkScoreService
+{
+ /**
+ * Update scores.
+ * @return whether the update was successful.
+ * @throws SecurityException if the caller is not the current active scorer.
+ */
+ boolean updateScores(in ScoredNetwork[] networks);
+
+ /**
+ * Clear all scores.
+ * @return whether the clear was successful.
+ * @throws SecurityException if the caller is neither the current active scorer nor the scorer
+ * manager.
+ */
+ boolean clearScores();
+
+ /**
+ * Set the active scorer and clear existing scores.
+ * @param packageName the package name of the new scorer to use.
+ * @return true if the operation succeeded, or false if the new package is not a valid scorer.
+ * @throws SecurityException if the caller is not the scorer manager.
+ */
+ boolean setActiveScorer(in String packageName);
+}
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index cc3ad3e..bc19658 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -19,11 +19,19 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* Information which identifies a specific network.
*
* @hide
*/
+// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
+// type, so that all networks appear the same and can be scored without concern to the network type
+// itself. However, because no such cross-type identifier currently exists in the Android framework,
+// and because systems might obtain information about networks from sources other than Android
+// devices, we need to provide identifying details about each specific network type (wifi, cell,
+// etc.) so that clients can pull out these details depending on the type of network.
public class NetworkKey implements Parcelable {
/** A wifi network, for which {@link #wifiKey} will be populated. */
@@ -79,6 +87,21 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ NetworkKey that = (NetworkKey) o;
+
+ return type == that.type && Objects.equals(wifiKey, that.wifiKey);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, wifiKey);
+ }
+
+ @Override
public String toString() {
switch (type) {
case TYPE_WIFI:
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 3430547..5e61613 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -19,6 +19,9 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
/**
* Class that manages communication between network subsystems and a network scorer.
@@ -40,7 +43,7 @@
* <p>The system keeps track of a default scorer application; at any time, only this application
* will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
* {@link #updateScores}. Applications may determine the current default scorer with
- * {@link #getDefaultScorerPackage()} and request to change the default scorer by sending an
+ * {@link #getActiveScorerPackage()} and request to change the default scorer by sending an
* {@link #ACTION_CHANGE_DEFAULT} broadcast with another scorer.
*
* @hide
@@ -81,38 +84,82 @@
public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
private final Context mContext;
+ private final INetworkScoreService mService;
/** @hide */
public NetworkScoreManager(Context context) {
mContext = context;
+ IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE);
+ mService = INetworkScoreService.Stub.asInterface(iBinder);
}
/**
- * Obtain the package name of the current default network scorer.
+ * Obtain the package name of the current active network scorer.
*
- * At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
+ * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
* broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
* determine the current scorer and offer the user the ability to select a different scorer via
* the {@link #ACTION_CHANGE_DEFAULT} intent.
- * @return the full package name of the current default scorer, or null if there is no active
+ * @return the full package name of the current active scorer, or null if there is no active
* scorer.
*/
- public String getDefaultScorerPackage() {
- // TODO: Implement.
- return null;
+ public String getActiveScorerPackage() {
+ return NetworkScorerAppManager.getActiveScorer(mContext);
}
/**
* Update network scores.
*
- * This may be called at any time to re-score active networks. Scores will generally be updated
- * quickly, but if this method is called too frequently, the scores may be held and applied at
- * a later time.
+ * <p>This may be called at any time to re-score active networks. Scores will generally be
+ * updated quickly, but if this method is called too frequently, the scores may be held and
+ * applied at a later time.
*
* @param networks the networks which have been scored by the scorer.
- * @throws SecurityException if the caller is not the default scorer.
+ * @return whether the update was successful.
+ * @throws SecurityException if the caller is not the active scorer.
*/
- public void updateScores(ScoredNetwork[] networks) throws SecurityException {
- // TODO: Implement.
+ public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
+ try {
+ return mService.updateScores(networks);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Clear network scores.
+ *
+ * <p>Should be called when all scores need to be invalidated, i.e. because the scoring
+ * algorithm has changed and old scores can no longer be compared to future scores.
+ *
+ * <p>Note that scores will be cleared automatically when the active scorer changes, as scores
+ * from one scorer cannot be compared to those from another scorer.
+ *
+ * @return whether the clear was successful.
+ * @throws SecurityException if the caller is not the active scorer or privileged.
+ */
+ public boolean clearScores() throws SecurityException {
+ try {
+ return mService.clearScores();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Set the active scorer to a new package and clear existing scores.
+ *
+ * @return true if the operation succeeded, or false if the new package is not a valid scorer.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that
+ * it can manage scorer applications.
+ * @hide
+ */
+ public boolean setActiveScorer(String packageName) throws SecurityException {
+ try {
+ return mService.setActiveScorer(packageName);
+ } catch (RemoteException e) {
+ return false;
+ }
}
}
diff --git a/core/java/android/net/NetworkScorerApplication.java b/core/java/android/net/NetworkScorerAppManager.java
similarity index 88%
rename from core/java/android/net/NetworkScorerApplication.java
rename to core/java/android/net/NetworkScorerAppManager.java
index b137ad3..726208a 100644
--- a/core/java/android/net/NetworkScorerApplication.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -26,6 +26,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.text.TextUtils;
+import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
@@ -36,13 +37,14 @@
*
* @hide
*/
-public final class NetworkScorerApplication {
+public final class NetworkScorerAppManager {
+ private static final String TAG = "NetworkScorerAppManager";
private static final Intent SCORE_INTENT =
new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
/** This class cannot be instantiated. */
- private NetworkScorerApplication() {}
+ private NetworkScorerAppManager() {}
/**
* Returns the list of available scorer app package names.
@@ -111,30 +113,38 @@
* @param context the context of the calling application
* @param packageName the packageName of the new scorer to use. If null, scoring will be
* disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
+ * @return true if the scorer was changed, or false if the package is not a valid scorer.
*/
- public static void setActiveScorer(Context context, String packageName) {
+ public static boolean setActiveScorer(Context context, String packageName) {
String oldPackageName = Settings.Global.getString(context.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP);
if (TextUtils.equals(oldPackageName, packageName)) {
// No change.
- return;
+ return true;
}
+ Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
+
if (packageName == null) {
Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP,
null);
+ return true;
} else {
// We only make the change if the new package is valid.
Collection<String> applications = getAllValidScorers(context);
if (isPackageValidScorer(applications, packageName)) {
Settings.Global.putString(context.getContentResolver(),
Settings.Global.NETWORK_SCORER_APP, packageName);
+ return true;
+ } else {
+ Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+ return false;
}
}
}
/** Determine whether the application with the given UID is the enabled scorer. */
- public static boolean isCallerDefaultScorer(Context context, int callingUid) {
+ public static boolean isCallerActiveScorer(Context context, int callingUid) {
String defaultApp = getActiveScorer(context);
if (defaultApp == null) {
return false;
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 7af7998..33e81c2 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -19,6 +19,9 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
* A curve defining the network score over a range of RSSI values.
*
@@ -94,6 +97,30 @@
out.writeByteArray(rssiBuckets);
}
+ /**
+ * Determine if two RSSI curves are defined in the same way.
+ *
+ * <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one
+ * curve is split into two buckets in another. For the purpose of this method, these curves are
+ * not considered equal to each other.
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ RssiCurve rssiCurve = (RssiCurve) o;
+
+ return start == rssiCurve.start &&
+ bucketWidth == rssiCurve.bucketWidth &&
+ Arrays.equals(rssiBuckets, rssiCurve.rssiBuckets);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(start, bucketWidth, rssiBuckets);
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 8af3c3c..7902313 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* A network identifier along with a score for the quality of that network.
*
@@ -80,6 +82,22 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ScoredNetwork that = (ScoredNetwork) o;
+
+ return Objects.equals(networkKey, that.networkKey) &&
+ Objects.equals(rssiCurve, that.rssiCurve);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(networkKey, rssiCurve);
+ }
+
+ @Override
public String toString() {
return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index a7a8a0a..ce70455 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -21,6 +21,7 @@
import android.os.Parcelable;
import android.os.StrictMode;
import android.util.Log;
+
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@@ -32,8 +33,10 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.RandomAccess;
import java.util.Set;
+
import libcore.net.UriCodec;
/**
@@ -2338,4 +2341,29 @@
StrictMode.onFileUriExposed(location);
}
}
+
+ /**
+ * Test if this is a path prefix match against the given Uri. Verifies that
+ * scheme, authority, and atomic path segments match.
+ *
+ * @hide
+ */
+ public boolean isPathPrefixMatch(Uri prefix) {
+ if (!Objects.equals(getScheme(), prefix.getScheme())) return false;
+ if (!Objects.equals(getAuthority(), prefix.getAuthority())) return false;
+
+ List<String> seg = getPathSegments();
+ List<String> prefixSeg = prefix.getPathSegments();
+
+ final int prefixSize = prefixSeg.size();
+ if (seg.size() < prefixSize) return false;
+
+ for (int i = 0; i < prefixSize; i++) {
+ if (!Objects.equals(seg.get(i), prefixSeg.get(i))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index ffcd85a..9e92e89 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -19,6 +19,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
import java.util.regex.Pattern;
/**
@@ -87,6 +88,21 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WifiKey wifiKey = (WifiKey) o;
+
+ return Objects.equals(ssid, wifiKey.ssid) && Objects.equals(bssid, wifiKey.bssid);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ssid, bssid);
+ }
+
+ @Override
public String toString() {
return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]";
}
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index b8a5ba7..ae9796b 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -17,6 +17,7 @@
package android.nfc;
import android.content.ComponentName;
+import android.nfc.cardemulation.AidGroup;
import android.nfc.cardemulation.ApduServiceInfo;
import android.os.RemoteCallback;
@@ -29,5 +30,8 @@
boolean isDefaultServiceForAid(int userHandle, in ComponentName service, String aid);
boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
boolean setDefaultForNextTap(int userHandle, in ComponentName service);
+ boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup);
+ AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
+ boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
List<ApduServiceInfo> getServices(int userHandle, in String category);
}
diff --git a/core/java/android/nfc/cardemulation/AidGroup.aidl b/core/java/android/nfc/cardemulation/AidGroup.aidl
new file mode 100644
index 0000000..56d6fa5
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/AidGroup.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2013 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.nfc.cardemulation;
+
+parcelable AidGroup;
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
new file mode 100644
index 0000000..2820f40
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -0,0 +1,165 @@
+package android.nfc.cardemulation;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * The AidGroup class represents a group of ISO/IEC 7816-4
+ * Application Identifiers (AIDs) for a specific application
+ * category, along with a description resource describing
+ * the group.
+ */
+public final class AidGroup implements Parcelable {
+ /**
+ * The maximum number of AIDs that can be present in any one group.
+ */
+ public static final int MAX_NUM_AIDS = 256;
+
+ static final String TAG = "AidGroup";
+
+ final ArrayList<String> aids;
+ final String category;
+ final String description;
+
+ /**
+ * Creates a new AidGroup object.
+ *
+ * @param aids The list of AIDs present in the group
+ * @param category The category of this group
+ */
+ public AidGroup(ArrayList<String> aids, String category) {
+ if (aids == null || aids.size() == 0) {
+ throw new IllegalArgumentException("No AIDS in AID group.");
+ }
+ if (aids.size() > MAX_NUM_AIDS) {
+ throw new IllegalArgumentException("Too many AIDs in AID group.");
+ }
+ if (!isValidCategory(category)) {
+ throw new IllegalArgumentException("Category specified is not valid.");
+ }
+ this.aids = aids;
+ this.category = category;
+ this.description = null;
+ }
+
+ AidGroup(String category, String description) {
+ this.aids = new ArrayList<String>();
+ this.category = category;
+ this.description = description;
+ }
+
+ /**
+ * @return the category of this AID group
+ */
+ public String getCategory() {
+ return category;
+ }
+
+ /**
+ * @return the list of AIDs in this group
+ */
+ public ArrayList<String> getAids() {
+ return aids;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder("Category: " + category +
+ ", AIDs:");
+ for (String aid : aids) {
+ out.append(aid);
+ out.append(", ");
+ }
+ return out.toString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(category);
+ dest.writeInt(aids.size());
+ if (aids.size() > 0) {
+ dest.writeStringList(aids);
+ }
+ }
+
+ public static final Parcelable.Creator<AidGroup> CREATOR =
+ new Parcelable.Creator<AidGroup>() {
+
+ @Override
+ public AidGroup createFromParcel(Parcel source) {
+ String category = source.readString();
+ int listSize = source.readInt();
+ ArrayList<String> aidList = new ArrayList<String>();
+ if (listSize > 0) {
+ source.readStringList(aidList);
+ }
+ return new AidGroup(aidList, category);
+ }
+
+ @Override
+ public AidGroup[] newArray(int size) {
+ return new AidGroup[size];
+ }
+ };
+
+ /**
+ * @hide
+ * Note: description is not serialized, since it's not localized
+ * and resource identifiers don't make sense to persist.
+ */
+ static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+ String category = parser.getAttributeValue(null, "category");
+ ArrayList<String> aids = new ArrayList<String>();
+ int eventType = parser.getEventType();
+ int minDepth = parser.getDepth();
+ while (eventType != XmlPullParser.END_DOCUMENT && parser.getDepth() >= minDepth) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tagName = parser.getName();
+ if (tagName.equals("aid")) {
+ String aid = parser.getAttributeValue(null, "value");
+ if (aid != null) {
+ aids.add(aid);
+ }
+ } else {
+ Log.d(TAG, "Ignorning unexpected tag: " + tagName);
+ }
+ }
+ eventType = parser.next();
+ }
+ if (category != null && aids.size() > 0) {
+ return new AidGroup(aids, category);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void writeAsXml(XmlSerializer out) throws IOException {
+ out.attribute(null, "category", category);
+ for (String aid : aids) {
+ out.startTag(null, "aid");
+ out.attribute(null, "value", aid);
+ out.endTag(null, "aid");
+ }
+ }
+
+ boolean isValidCategory(String category) {
+ return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
+ CardEmulation.CATEGORY_OTHER.equals(category);
+ }
+}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index d7ef4bc..94f35ed 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -35,9 +35,12 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
/**
* @hide
@@ -56,24 +59,19 @@
final String mDescription;
/**
- * Convenience AID list
- */
- final ArrayList<String> mAids;
-
- /**
* Whether this service represents AIDs running on the host CPU
*/
final boolean mOnHost;
/**
- * All AID groups this service handles
+ * Mapping from category to static AID group
*/
- final ArrayList<AidGroup> mAidGroups;
+ final HashMap<String, AidGroup> mStaticAidGroups;
/**
- * Convenience hashmap
+ * Mapping from category to dynamic AID group
*/
- final HashMap<String, AidGroup> mCategoryToGroup;
+ final HashMap<String, AidGroup> mDynamicAidGroups;
/**
* Whether this service should only be started when the device is unlocked.
@@ -86,26 +84,33 @@
final int mBannerResourceId;
/**
+ * The uid of the package the service belongs to
+ */
+ final int mUid;
+ /**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> aidGroups, boolean requiresUnlock, int bannerResource) {
+ ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+ boolean requiresUnlock, int bannerResource, int uid) {
this.mService = info;
this.mDescription = description;
- this.mAidGroups = aidGroups;
- this.mAids = new ArrayList<String>();
- this.mCategoryToGroup = new HashMap<String, AidGroup>();
+ this.mStaticAidGroups = new HashMap<String, AidGroup>();
+ this.mDynamicAidGroups = new HashMap<String, AidGroup>();
this.mOnHost = onHost;
this.mRequiresDeviceUnlock = requiresUnlock;
- for (AidGroup aidGroup : aidGroups) {
- this.mCategoryToGroup.put(aidGroup.category, aidGroup);
- this.mAids.addAll(aidGroup.aids);
+ for (AidGroup aidGroup : staticAidGroups) {
+ this.mStaticAidGroups.put(aidGroup.category, aidGroup);
+ }
+ for (AidGroup aidGroup : dynamicAidGroups) {
+ this.mDynamicAidGroups.put(aidGroup.category, aidGroup);
}
this.mBannerResourceId = bannerResource;
+ this.mUid = uid;
}
- public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost)
- throws XmlPullParserException, IOException {
+ public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
+ XmlPullParserException, IOException {
ServiceInfo si = info.serviceInfo;
XmlResourceParser parser = null;
try {
@@ -163,10 +168,10 @@
sa.recycle();
}
- mAidGroups = new ArrayList<AidGroup>();
- mCategoryToGroup = new HashMap<String, AidGroup>();
- mAids = new ArrayList<String>();
+ mStaticAidGroups = new HashMap<String, AidGroup>();
+ mDynamicAidGroups = new HashMap<String, AidGroup>();
mOnHost = onHost;
+
final int depth = parser.getDepth();
AidGroup currentGroup = null;
@@ -179,14 +184,14 @@
final TypedArray groupAttrs = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AidGroup);
// Get category of AID group
- String groupDescription = groupAttrs.getString(
- com.android.internal.R.styleable.AidGroup_description);
String groupCategory = groupAttrs.getString(
com.android.internal.R.styleable.AidGroup_category);
+ String groupDescription = groupAttrs.getString(
+ com.android.internal.R.styleable.AidGroup_description);
if (!CardEmulation.CATEGORY_PAYMENT.equals(groupCategory)) {
groupCategory = CardEmulation.CATEGORY_OTHER;
}
- currentGroup = mCategoryToGroup.get(groupCategory);
+ currentGroup = mStaticAidGroups.get(groupCategory);
if (currentGroup != null) {
if (!CardEmulation.CATEGORY_OTHER.equals(groupCategory)) {
Log.e(TAG, "Not allowing multiple aid-groups in the " +
@@ -200,9 +205,8 @@
} else if (eventType == XmlPullParser.END_TAG && "aid-group".equals(tagName) &&
currentGroup != null) {
if (currentGroup.aids.size() > 0) {
- if (!mCategoryToGroup.containsKey(currentGroup.category)) {
- mAidGroups.add(currentGroup);
- mCategoryToGroup.put(currentGroup.category, currentGroup);
+ if (!mStaticAidGroups.containsKey(currentGroup.category)) {
+ mStaticAidGroups.put(currentGroup.category, currentGroup);
}
} else {
Log.e(TAG, "Not adding <aid-group> with empty or invalid AIDs");
@@ -216,7 +220,6 @@
toUpperCase();
if (isValidAid(aid) && !currentGroup.aids.contains(aid)) {
currentGroup.aids.add(aid);
- mAids.add(aid);
} else {
Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
}
@@ -228,6 +231,8 @@
} finally {
if (parser != null) parser.close();
}
+ // Set uid
+ mUid = si.applicationInfo.uid;
}
public ComponentName getComponent() {
@@ -235,16 +240,58 @@
mService.serviceInfo.name);
}
+ /**
+ * Returns a consolidated list of AIDs from the AID groups
+ * registered by this service. Note that if a service has both
+ * a static (manifest-based) AID group for a category and a dynamic
+ * AID group, only the dynamically registered AIDs will be returned
+ * for that category.
+ * @return List of AIDs registered by the service
+ */
public ArrayList<String> getAids() {
- return mAids;
+ final ArrayList<String> aids = new ArrayList<String>();
+ for (AidGroup group : getAidGroups()) {
+ aids.addAll(group.aids);
+ }
+ return aids;
}
+ /**
+ * Returns the registered AID group for this category.
+ */
+ public AidGroup getDynamicAidGroupForCategory(String category) {
+ return mDynamicAidGroups.get(category);
+ }
+
+ public boolean removeDynamicAidGroupForCategory(String category) {
+ return (mDynamicAidGroups.remove(category) != null);
+ }
+
+ /**
+ * Returns a consolidated list of AID groups
+ * registered by this service. Note that if a service has both
+ * a static (manifest-based) AID group for a category and a dynamic
+ * AID group, only the dynamically registered AID group will be returned
+ * for that category.
+ * @return List of AIDs registered by the service
+ */
public ArrayList<AidGroup> getAidGroups() {
- return mAidGroups;
+ final ArrayList<AidGroup> groups = new ArrayList<AidGroup>();
+ for (Map.Entry<String, AidGroup> entry : mDynamicAidGroups.entrySet()) {
+ groups.add(entry.getValue());
+ }
+ for (Map.Entry<String, AidGroup> entry : mStaticAidGroups.entrySet()) {
+ if (!mDynamicAidGroups.containsKey(entry.getKey())) {
+ // Consolidate AID groups - don't return static ones
+ // if a dynamic group exists for the category.
+ groups.add(entry.getValue());
+ }
+ }
+ return groups;
}
public boolean hasCategory(String category) {
- return mCategoryToGroup.containsKey(category);
+ return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
}
public boolean isOnHost() {
@@ -259,6 +306,14 @@
return mDescription;
}
+ public int getUid() {
+ return mUid;
+ }
+
+ public void setOrReplaceDynamicAidGroup(AidGroup aidGroup) {
+ mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
+ }
+
public CharSequence loadLabel(PackageManager pm) {
return mService.loadLabel(pm);
}
@@ -304,8 +359,12 @@
StringBuilder out = new StringBuilder("ApduService: ");
out.append(getComponent());
out.append(", description: " + mDescription);
- out.append(", AID Groups: ");
- for (AidGroup aidGroup : mAidGroups) {
+ out.append(", Static AID Groups: ");
+ for (AidGroup aidGroup : mStaticAidGroups.values()) {
+ out.append(aidGroup.toString());
+ }
+ out.append(", Dynamic AID Groups: ");
+ for (AidGroup aidGroup : mDynamicAidGroups.values()) {
out.append(aidGroup.toString());
}
return out.toString();
@@ -336,12 +395,17 @@
mService.writeToParcel(dest, flags);
dest.writeString(mDescription);
dest.writeInt(mOnHost ? 1 : 0);
- dest.writeInt(mAidGroups.size());
- if (mAidGroups.size() > 0) {
- dest.writeTypedList(mAidGroups);
+ dest.writeInt(mStaticAidGroups.size());
+ if (mStaticAidGroups.size() > 0) {
+ dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values()));
+ }
+ dest.writeInt(mDynamicAidGroups.size());
+ if (mDynamicAidGroups.size() > 0) {
+ dest.writeTypedList(new ArrayList<AidGroup>(mDynamicAidGroups.values()));
}
dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
dest.writeInt(mBannerResourceId);
+ dest.writeInt(mUid);
};
public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -351,14 +415,21 @@
ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
String description = source.readString();
boolean onHost = (source.readInt() != 0) ? true : false;
- ArrayList<AidGroup> aidGroups = new ArrayList<AidGroup>();
- int numGroups = source.readInt();
- if (numGroups > 0) {
- source.readTypedList(aidGroups, AidGroup.CREATOR);
+ ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
+ int numStaticGroups = source.readInt();
+ if (numStaticGroups > 0) {
+ source.readTypedList(staticAidGroups, AidGroup.CREATOR);
+ }
+ ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
+ int numDynamicGroups = source.readInt();
+ if (numDynamicGroups > 0) {
+ source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
}
boolean requiresUnlock = (source.readInt() != 0) ? true : false;
int bannerResource = source.readInt();
- return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock, bannerResource);
+ int uid = source.readInt();
+ return new ApduServiceInfo(info, onHost, description, staticAidGroups,
+ dynamicAidGroups, requiresUnlock, bannerResource, uid);
}
@Override
@@ -367,76 +438,22 @@
}
};
- public static class AidGroup implements Parcelable {
- final ArrayList<String> aids;
- final String category;
- final String description;
-
- AidGroup(ArrayList<String> aids, String category, String description) {
- this.aids = aids;
- this.category = category;
- this.description = description;
- }
-
- AidGroup(String category, String description) {
- this.aids = new ArrayList<String>();
- this.category = category;
- this.description = description;
- }
-
- public String getCategory() {
- return category;
- }
-
- public ArrayList<String> getAids() {
- return aids;
- }
-
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder("Category: " + category +
- ", description: " + description + ", AIDs:");
- for (String aid : aids) {
- out.append(aid);
- out.append(", ");
- }
- return out.toString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(category);
- dest.writeString(description);
- dest.writeInt(aids.size());
- if (aids.size() > 0) {
- dest.writeStringList(aids);
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(" " + getComponent() +
+ " (Description: " + getDescription() + ")");
+ pw.println(" Static AID groups:");
+ for (AidGroup group : mStaticAidGroups.values()) {
+ pw.println(" Category: " + group.category);
+ for (String aid : group.aids) {
+ pw.println(" AID: " + aid);
}
}
-
- public static final Parcelable.Creator<ApduServiceInfo.AidGroup> CREATOR =
- new Parcelable.Creator<ApduServiceInfo.AidGroup>() {
-
- @Override
- public AidGroup createFromParcel(Parcel source) {
- String category = source.readString();
- String description = source.readString();
- int listSize = source.readInt();
- ArrayList<String> aidList = new ArrayList<String>();
- if (listSize > 0) {
- source.readStringList(aidList);
- }
- return new AidGroup(aidList, category, description);
+ pw.println(" Dynamic AID groups:");
+ for (AidGroup group : mDynamicAidGroups.values()) {
+ pw.println(" Category: " + group.category);
+ for (String aid : group.aids) {
+ pw.println(" AID: " + aid);
}
-
- @Override
- public AidGroup[] newArray(int size) {
- return new AidGroup[size];
- }
- };
+ }
}
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 58d9616..41f039c 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -168,6 +168,10 @@
if (manager == null) {
// Get card emu service
INfcCardEmulation service = adapter.getCardEmulationService();
+ if (service == null) {
+ Log.e(TAG, "This device does not implement the INfcCardEmulation interface.");
+ throw new UnsupportedOperationException();
+ }
manager = new CardEmulation(context, service);
sCardEmus.put(context, manager);
}
@@ -271,6 +275,109 @@
}
/**
+ * Registers a group of AIDs for the specified service.
+ *
+ * <p>If an AID group for that category was previously
+ * registered for this service (either statically
+ * through the manifest, or dynamically by using this API),
+ * that AID group will be replaced with this one.
+ *
+ * <p>Note that you can only register AIDs for a service that
+ * is running under the same UID as you are. Typically
+ * this means you need to call this from the same
+ * package as the service itself, though UIDs can also
+ * be shared between packages using shared UIDs.
+ *
+ * @param service The component name of the service
+ * @param aidGroup The group of AIDs to be registered
+ * @return whether the registration was successful.
+ */
+ public boolean registerAidGroupForService(ComponentName service, AidGroup aidGroup) {
+ try {
+ return sService.registerAidGroupForService(UserHandle.myUserId(), service, aidGroup);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.registerAidGroupForService(UserHandle.myUserId(), service,
+ aidGroup);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the currently registered AID group for the specified
+ * category for a service.
+ *
+ * <p>Note that this will only return AID groups that were dynamically
+ * registered using {@link #registerAidGroupForService(ComponentName, AidGroup)}
+ * method. It will *not* return AID groups that were statically registered
+ * in the manifest.
+ *
+ * @param service The component name of the service
+ * @param category The category of the AID group to be returned, e.g. {@link #CATEGORY_PAYMENT}
+ * @return The AID group, or null if it couldn't be found
+ */
+ public AidGroup getAidGroupForService(ComponentName service, String category) {
+ try {
+ return sService.getAidGroupForService(UserHandle.myUserId(), service, category);
+ } catch (RemoteException e) {
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ try {
+ return sService.getAidGroupForService(UserHandle.myUserId(), service, category);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Removes a registered AID group for the specified category for the
+ * service provided.
+ *
+ * <p>Note that this will only remove AID groups that were dynamically
+ * registered using the {@link #registerAidGroupForService(ComponentName, AidGroup)}
+ * method. It will *not* remove AID groups that were statically registered in
+ * the manifest. If a dynamically registered AID group is removed using
+ * this method, and a statically registered AID group for the same category
+ * exists in the manifest, that AID group will become active again.
+ *
+ * @param service The component name of the service
+ * @param category The category of the AID group to be removed, e.g. {@link #CATEGORY_PAYMENT}
+ * @return whether the group was successfully removed.
+ */
+ public boolean removeAidGroupForService(ComponentName service, String category) {
+ try {
+ return sService.removeAidGroupForService(UserHandle.myUserId(), service, category);
+ } catch (RemoteException e) {
+ // Try one more time
+ recoverService();
+ if (sService == null) {
+ Log.e(TAG, "Failed to recover CardEmulationService.");
+ return false;
+ }
+ try {
+ return sService.removeAidGroupForService(UserHandle.myUserId(), service, category);
+ } catch (RemoteException ee) {
+ Log.e(TAG, "Failed to reach CardEmulationService.");
+ return false;
+ }
+ }
+ }
+
+ /**
* @hide
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 426f21e..e640649 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2861,29 +2861,21 @@
int oldTemp = -1;
int oldVolt = -1;
long lastTime = -1;
+ long firstTime = -1;
- public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin,
+ public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
boolean verbose) {
if (!checkin) {
pw.print(" ");
- if (now >= 0) {
- TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
- } else {
- TimeUtils.formatDuration(rec.time, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
- }
+ TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" (");
pw.print(rec.numReadInts);
pw.print(") ");
} else {
if (lastTime < 0) {
- if (now >= 0) {
- pw.print("@");
- pw.print(rec.time-now);
- } else {
- pw.print(rec.time);
- }
+ pw.print(rec.time - baseTime);
} else {
- pw.print(rec.time-lastTime);
+ pw.print(rec.time - lastTime);
}
lastTime = rec.time;
}
@@ -3132,10 +3124,27 @@
pw.println("):");
HistoryPrinter hprinter = new HistoryPrinter();
long lastTime = -1;
+ long baseTime = -1;
+ boolean printed = false;
while (getNextHistoryLocked(rec)) {
lastTime = rec.time;
+ if (baseTime < 0) {
+ baseTime = lastTime;
+ }
if (rec.time >= histStart) {
- hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false,
+ if (histStart >= 0 && !printed) {
+ if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+ printed = true;
+ } else if (rec.currentTime != 0) {
+ printed = true;
+ byte cmd = rec.cmd;
+ rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+ hprinter.printNextItem(pw, rec, baseTime, false,
+ (flags&DUMP_VERBOSE) != 0);
+ rec.cmd = cmd;
+ }
+ }
+ hprinter.printNextItem(pw, rec, baseTime, false,
(flags&DUMP_VERBOSE) != 0);
}
}
@@ -3152,8 +3161,12 @@
try {
pw.println("Old battery History:");
HistoryPrinter hprinter = new HistoryPrinter();
+ long baseTime = -1;
while (getNextOldHistoryLocked(rec)) {
- hprinter.printNextItem(pw, rec, now, false, (flags&DUMP_VERBOSE) != 0);
+ if (baseTime < 0) {
+ baseTime = rec.time;
+ }
+ hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
}
pw.println();
} finally {
@@ -3226,20 +3239,42 @@
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(HISTORY_STRING_POOL); pw.print(',');
pw.print(i);
- pw.print(',');
- pw.print(getHistoryTagPoolString(i));
- pw.print(',');
+ pw.print(",");
pw.print(getHistoryTagPoolUid(i));
+ pw.print(",\"");
+ String str = getHistoryTagPoolString(i);
+ str = str.replace("\\", "\\\\");
+ str = str.replace("\"", "\\\"");
+ pw.print(str);
+ pw.print("\"");
pw.println();
}
HistoryPrinter hprinter = new HistoryPrinter();
long lastTime = -1;
+ long baseTime = -1;
+ boolean printed = false;
while (getNextHistoryLocked(rec)) {
lastTime = rec.time;
+ if (baseTime < 0) {
+ baseTime = lastTime;
+ }
if (rec.time >= histStart) {
+ if (histStart >= 0 && !printed) {
+ if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+ printed = true;
+ } else if (rec.currentTime != 0) {
+ printed = true;
+ byte cmd = rec.cmd;
+ rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
+ hprinter.printNextItem(pw, rec, baseTime, true, false);
+ rec.cmd = cmd;
+ }
+ }
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(HISTORY_DATA); pw.print(',');
- hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true, false);
+ hprinter.printNextItem(pw, rec, baseTime, true, false);
}
}
if (histStart >= 0) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 63e15a9..19be2c8 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -487,7 +487,7 @@
* new changes in behavior:</p>
* <ul>
* <li> {@link android.content.Context#bindService Context.bindService} now
- * requires an explicit Intent, and will throw an exception if given an explicit
+ * requires an explicit Intent, and will throw an exception if given an implicit
* Intent.</li>
* </ul>
*/
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index af57507..c85e418 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,7 +17,6 @@
package android.os;
import android.util.ArrayMap;
-import android.util.Log;
import android.util.SparseArray;
import java.io.Serializable;
@@ -29,47 +28,25 @@
* A mapping from String values to various Parcelable types.
*
*/
-public final class Bundle implements Parcelable, Cloneable {
- private static final String TAG = "Bundle";
- static final boolean DEBUG = false;
+public final class Bundle extends CommonBundle {
public static final Bundle EMPTY;
-
- static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
static final Parcel EMPTY_PARCEL;
static {
EMPTY = new Bundle();
EMPTY.mMap = ArrayMap.EMPTY;
- EMPTY_PARCEL = Parcel.obtain();
+ EMPTY_PARCEL = CommonBundle.EMPTY_PARCEL;
}
- // Invariant - exactly one of mMap / mParcelledData will be null
- // (except inside a call to unparcel)
-
- /* package */ ArrayMap<String, Object> mMap = null;
-
- /*
- * If mParcelledData is non-null, then mMap will be null and the
- * data are stored as a Parcel containing a Bundle. When the data
- * are unparcelled, mParcelledData willbe set to null.
- */
- /* package */ Parcel mParcelledData = null;
-
private boolean mHasFds = false;
private boolean mFdsKnown = true;
private boolean mAllowFds = true;
/**
- * The ClassLoader used when unparcelling data from mParcelledData.
- */
- private ClassLoader mClassLoader;
-
- /**
* Constructs a new, empty Bundle.
*/
public Bundle() {
- mMap = new ArrayMap<String, Object>();
- mClassLoader = getClass().getClassLoader();
+ super();
}
/**
@@ -79,11 +56,17 @@
* @param parcelledData a Parcel containing a Bundle
*/
Bundle(Parcel parcelledData) {
- readFromParcel(parcelledData);
+ super(parcelledData);
+
+ mHasFds = mParcelledData.hasFileDescriptors();
+ mFdsKnown = true;
}
/* package */ Bundle(Parcel parcelledData, int length) {
- readFromParcelInner(parcelledData, length);
+ super(parcelledData, length);
+
+ mHasFds = mParcelledData.hasFileDescriptors();
+ mFdsKnown = true;
}
/**
@@ -94,8 +77,7 @@
* inside of the Bundle.
*/
public Bundle(ClassLoader loader) {
- mMap = new ArrayMap<String, Object>();
- mClassLoader = loader;
+ super(loader);
}
/**
@@ -105,8 +87,7 @@
* @param capacity the initial capacity of the Bundle
*/
public Bundle(int capacity) {
- mMap = new ArrayMap<String, Object>(capacity);
- mClassLoader = getClass().getClassLoader();
+ super(capacity);
}
/**
@@ -116,27 +97,20 @@
* @param b a Bundle to be copied.
*/
public Bundle(Bundle b) {
- if (b.mParcelledData != null) {
- if (b.mParcelledData == EMPTY_PARCEL) {
- mParcelledData = EMPTY_PARCEL;
- } else {
- mParcelledData = Parcel.obtain();
- mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
- mParcelledData.setDataPosition(0);
- }
- } else {
- mParcelledData = null;
- }
-
- if (b.mMap != null) {
- mMap = new ArrayMap<String, Object>(b.mMap);
- } else {
- mMap = null;
- }
+ super(b);
mHasFds = b.mHasFds;
mFdsKnown = b.mFdsKnown;
- mClassLoader = b.mClassLoader;
+ }
+
+ /**
+ * Constructs a Bundle containing a copy of the mappings from the given
+ * PersistableBundle.
+ *
+ * @param b a Bundle to be copied.
+ */
+ public Bundle(PersistableBundle b) {
+ super(b);
}
/**
@@ -145,37 +119,17 @@
* @hide
*/
public static Bundle forPair(String key, String value) {
- // TODO: optimize this case.
Bundle b = new Bundle(1);
b.putString(key, value);
return b;
}
/**
- * TODO: optimize this later (getting just the value part of a Bundle
- * with a single pair) once Bundle.forPair() above is implemented
- * with a special single-value Map implementation/serialization.
- *
- * Note: value in single-pair Bundle may be null.
- *
* @hide
*/
+ @Override
public String getPairValue() {
- unparcel();
- int size = mMap.size();
- if (size > 1) {
- Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
- }
- if (size == 0) {
- return null;
- }
- Object o = mMap.valueAt(0);
- try {
- return (String) o;
- } catch (ClassCastException e) {
- typeWarning("getPairValue()", o, "String", e);
- return null;
- }
+ return super.getPairValue();
}
/**
@@ -184,15 +138,17 @@
* @param loader An explicit ClassLoader to use when instantiating objects
* inside of the Bundle.
*/
+ @Override
public void setClassLoader(ClassLoader loader) {
- mClassLoader = loader;
+ super.setClassLoader(loader);
}
/**
* Return the ClassLoader currently associated with this Bundle.
*/
+ @Override
public ClassLoader getClassLoader() {
- return mClassLoader;
+ return super.getClassLoader();
}
/** @hide */
@@ -212,52 +168,11 @@
}
/**
- * If the underlying data are stored as a Parcel, unparcel them
- * using the currently assigned class loader.
- */
- /* package */ synchronized void unparcel() {
- if (mParcelledData == null) {
- if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
- + ": no parcelled data");
- return;
- }
-
- if (mParcelledData == EMPTY_PARCEL) {
- if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
- + ": empty");
- if (mMap == null) {
- mMap = new ArrayMap<String, Object>(1);
- } else {
- mMap.erase();
- }
- mParcelledData = null;
- return;
- }
-
- int N = mParcelledData.readInt();
- if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
- + ": reading " + N + " maps");
- if (N < 0) {
- return;
- }
- if (mMap == null) {
- mMap = new ArrayMap<String, Object>(N);
- } else {
- mMap.erase();
- mMap.ensureCapacity(N);
- }
- mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
- mParcelledData.recycle();
- mParcelledData = null;
- if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
- + " final map: " + mMap);
- }
-
- /**
* @hide
*/
+ @Override
public boolean isParcelled() {
- return mParcelledData != null;
+ return super.isParcelled();
}
/**
@@ -265,25 +180,26 @@
*
* @return the number of mappings as an int.
*/
+ @Override
public int size() {
- unparcel();
- return mMap.size();
+ return super.size();
}
/**
* Returns true if the mapping of this Bundle is empty, false otherwise.
*/
+ @Override
public boolean isEmpty() {
- unparcel();
- return mMap.isEmpty();
+ return super.isEmpty();
}
/**
* Removes all elements from the mapping of this Bundle.
*/
+ @Override
public void clear() {
- unparcel();
- mMap.clear();
+ super.clear();
+
mHasFds = false;
mFdsKnown = true;
}
@@ -295,9 +211,9 @@
* @param key a String key
* @return true if the key is part of the mapping, false otherwise
*/
+ @Override
public boolean containsKey(String key) {
- unparcel();
- return mMap.containsKey(key);
+ return super.containsKey(key);
}
/**
@@ -306,9 +222,9 @@
* @param key a String key
* @return an Object, or null
*/
+ @Override
public Object get(String key) {
- unparcel();
- return mMap.get(key);
+ return super.get(key);
}
/**
@@ -316,24 +232,33 @@
*
* @param key a String key
*/
+ @Override
public void remove(String key) {
- unparcel();
- mMap.remove(key);
+ super.remove(key);
}
/**
* Inserts all mappings from the given Bundle into this Bundle.
*
- * @param map a Bundle
+ * @param bundle a Bundle
*/
- public void putAll(Bundle map) {
+ public void putAll(Bundle bundle) {
unparcel();
- map.unparcel();
- mMap.putAll(map.mMap);
+ bundle.unparcel();
+ mMap.putAll(bundle.mMap);
// fd state is now known if and only if both bundles already knew
- mHasFds |= map.mHasFds;
- mFdsKnown = mFdsKnown && map.mFdsKnown;
+ mHasFds |= bundle.mHasFds;
+ mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+ }
+
+ /**
+ * Inserts all mappings from the given PersistableBundle into this Bundle.
+ *
+ * @param bundle a PersistableBundle
+ */
+ public void putAll(PersistableBundle bundle) {
+ super.putAll(bundle);
}
/**
@@ -341,9 +266,9 @@
*
* @return a Set of String keys
*/
+ @Override
public Set<String> keySet() {
- unparcel();
- return mMap.keySet();
+ return super.keySet();
}
/**
@@ -352,7 +277,7 @@
public boolean hasFileDescriptors() {
if (!mFdsKnown) {
boolean fdFound = false; // keep going until we find one or run out of data
-
+
if (mParcelledData != null) {
if (mParcelledData.hasFileDescriptors()) {
fdFound = true;
@@ -390,8 +315,7 @@
ArrayList array = (ArrayList) obj;
// an ArrayList here might contain either Strings or
// Parcelables; only look inside for Parcelables
- if ((array.size() > 0)
- && (array.get(0) instanceof Parcelable)) {
+ if (!array.isEmpty() && (array.get(0) instanceof Parcelable)) {
for (int n = array.size() - 1; n >= 0; n--) {
Parcelable p = (Parcelable) array.get(n);
if (p != null && ((p.describeContents()
@@ -410,7 +334,7 @@
}
return mHasFds;
}
-
+
/**
* Inserts a Boolean value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
@@ -418,9 +342,9 @@
* @param key a String, or null
* @param value a Boolean, or null
*/
+ @Override
public void putBoolean(String key, boolean value) {
- unparcel();
- mMap.put(key, value);
+ super.putBoolean(key, value);
}
/**
@@ -430,9 +354,9 @@
* @param key a String, or null
* @param value a byte
*/
+ @Override
public void putByte(String key, byte value) {
- unparcel();
- mMap.put(key, value);
+ super.putByte(key, value);
}
/**
@@ -442,9 +366,9 @@
* @param key a String, or null
* @param value a char, or null
*/
+ @Override
public void putChar(String key, char value) {
- unparcel();
- mMap.put(key, value);
+ super.putChar(key, value);
}
/**
@@ -454,9 +378,9 @@
* @param key a String, or null
* @param value a short
*/
+ @Override
public void putShort(String key, short value) {
- unparcel();
- mMap.put(key, value);
+ super.putShort(key, value);
}
/**
@@ -466,9 +390,9 @@
* @param key a String, or null
* @param value an int, or null
*/
+ @Override
public void putInt(String key, int value) {
- unparcel();
- mMap.put(key, value);
+ super.putInt(key, value);
}
/**
@@ -478,9 +402,9 @@
* @param key a String, or null
* @param value a long
*/
+ @Override
public void putLong(String key, long value) {
- unparcel();
- mMap.put(key, value);
+ super.putLong(key, value);
}
/**
@@ -490,9 +414,9 @@
* @param key a String, or null
* @param value a float
*/
+ @Override
public void putFloat(String key, float value) {
- unparcel();
- mMap.put(key, value);
+ super.putFloat(key, value);
}
/**
@@ -502,9 +426,9 @@
* @param key a String, or null
* @param value a double
*/
+ @Override
public void putDouble(String key, double value) {
- unparcel();
- mMap.put(key, value);
+ super.putDouble(key, value);
}
/**
@@ -514,9 +438,9 @@
* @param key a String, or null
* @param value a String, or null
*/
+ @Override
public void putString(String key, String value) {
- unparcel();
- mMap.put(key, value);
+ super.putString(key, value);
}
/**
@@ -526,9 +450,9 @@
* @param key a String, or null
* @param value a CharSequence, or null
*/
+ @Override
public void putCharSequence(String key, CharSequence value) {
- unparcel();
- mMap.put(key, value);
+ super.putCharSequence(key, value);
}
/**
@@ -567,7 +491,7 @@
* @param value an ArrayList of Parcelable objects, or null
*/
public void putParcelableArrayList(String key,
- ArrayList<? extends Parcelable> value) {
+ ArrayList<? extends Parcelable> value) {
unparcel();
mMap.put(key, value);
mFdsKnown = false;
@@ -602,9 +526,9 @@
* @param key a String, or null
* @param value an ArrayList<Integer> object, or null
*/
+ @Override
public void putIntegerArrayList(String key, ArrayList<Integer> value) {
- unparcel();
- mMap.put(key, value);
+ super.putIntegerArrayList(key, value);
}
/**
@@ -614,9 +538,9 @@
* @param key a String, or null
* @param value an ArrayList<String> object, or null
*/
+ @Override
public void putStringArrayList(String key, ArrayList<String> value) {
- unparcel();
- mMap.put(key, value);
+ super.putStringArrayList(key, value);
}
/**
@@ -626,9 +550,9 @@
* @param key a String, or null
* @param value an ArrayList<CharSequence> object, or null
*/
+ @Override
public void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
- unparcel();
- mMap.put(key, value);
+ super.putCharSequenceArrayList(key, value);
}
/**
@@ -638,9 +562,9 @@
* @param key a String, or null
* @param value a Serializable object, or null
*/
+ @Override
public void putSerializable(String key, Serializable value) {
- unparcel();
- mMap.put(key, value);
+ super.putSerializable(key, value);
}
/**
@@ -650,9 +574,9 @@
* @param key a String, or null
* @param value a boolean array object, or null
*/
+ @Override
public void putBooleanArray(String key, boolean[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putBooleanArray(key, value);
}
/**
@@ -662,9 +586,9 @@
* @param key a String, or null
* @param value a byte array object, or null
*/
+ @Override
public void putByteArray(String key, byte[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putByteArray(key, value);
}
/**
@@ -674,9 +598,9 @@
* @param key a String, or null
* @param value a short array object, or null
*/
+ @Override
public void putShortArray(String key, short[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putShortArray(key, value);
}
/**
@@ -686,9 +610,9 @@
* @param key a String, or null
* @param value a char array object, or null
*/
+ @Override
public void putCharArray(String key, char[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putCharArray(key, value);
}
/**
@@ -698,9 +622,9 @@
* @param key a String, or null
* @param value an int array object, or null
*/
+ @Override
public void putIntArray(String key, int[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putIntArray(key, value);
}
/**
@@ -710,9 +634,9 @@
* @param key a String, or null
* @param value a long array object, or null
*/
+ @Override
public void putLongArray(String key, long[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putLongArray(key, value);
}
/**
@@ -722,9 +646,9 @@
* @param key a String, or null
* @param value a float array object, or null
*/
+ @Override
public void putFloatArray(String key, float[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putFloatArray(key, value);
}
/**
@@ -734,9 +658,9 @@
* @param key a String, or null
* @param value a double array object, or null
*/
+ @Override
public void putDoubleArray(String key, double[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putDoubleArray(key, value);
}
/**
@@ -746,9 +670,9 @@
* @param key a String, or null
* @param value a String array object, or null
*/
+ @Override
public void putStringArray(String key, String[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putStringArray(key, value);
}
/**
@@ -758,9 +682,9 @@
* @param key a String, or null
* @param value a CharSequence array object, or null
*/
+ @Override
public void putCharSequenceArray(String key, CharSequence[] value) {
- unparcel();
- mMap.put(key, value);
+ super.putCharSequenceArray(key, value);
}
/**
@@ -776,6 +700,17 @@
}
/**
+ * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Bundle object, or null
+ */
+ public void putPersistableBundle(String key, PersistableBundle value) {
+ super.putPersistableBundle(key, value);
+ }
+
+ /**
* Inserts an {@link IBinder} value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
@@ -817,33 +752,9 @@
* @param key a String
* @return a boolean value
*/
+ @Override
public boolean getBoolean(String key) {
- unparcel();
- if (DEBUG) Log.d(TAG, "Getting boolean in "
- + Integer.toHexString(System.identityHashCode(this)));
- return getBoolean(key, false);
- }
-
- // Log a message if the value was non-null but not of the expected type
- private void typeWarning(String key, Object value, String className,
- Object defaultValue, ClassCastException e) {
- StringBuilder sb = new StringBuilder();
- sb.append("Key ");
- sb.append(key);
- sb.append(" expected ");
- sb.append(className);
- sb.append(" but value was a ");
- sb.append(value.getClass().getName());
- sb.append(". The default value ");
- sb.append(defaultValue);
- sb.append(" was returned.");
- Log.w(TAG, sb.toString());
- Log.w(TAG, "Attempt to cast generated internal exception:", e);
- }
-
- private void typeWarning(String key, Object value, String className,
- ClassCastException e) {
- typeWarning(key, value, className, "<null>", e);
+ return super.getBoolean(key);
}
/**
@@ -854,18 +765,9 @@
* @param defaultValue Value to return if key does not exist
* @return a boolean value
*/
+ @Override
public boolean getBoolean(String key, boolean defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Boolean) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Boolean", defaultValue, e);
- return defaultValue;
- }
+ return super.getBoolean(key, defaultValue);
}
/**
@@ -875,9 +777,9 @@
* @param key a String
* @return a byte value
*/
+ @Override
public byte getByte(String key) {
- unparcel();
- return getByte(key, (byte) 0);
+ return super.getByte(key);
}
/**
@@ -888,18 +790,9 @@
* @param defaultValue Value to return if key does not exist
* @return a byte value
*/
+ @Override
public Byte getByte(String key, byte defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Byte) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Byte", defaultValue, e);
- return defaultValue;
- }
+ return super.getByte(key, defaultValue);
}
/**
@@ -909,9 +802,9 @@
* @param key a String
* @return a char value
*/
+ @Override
public char getChar(String key) {
- unparcel();
- return getChar(key, (char) 0);
+ return super.getChar(key);
}
/**
@@ -922,18 +815,9 @@
* @param defaultValue Value to return if key does not exist
* @return a char value
*/
+ @Override
public char getChar(String key, char defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Character) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Character", defaultValue, e);
- return defaultValue;
- }
+ return super.getChar(key, defaultValue);
}
/**
@@ -943,9 +827,9 @@
* @param key a String
* @return a short value
*/
+ @Override
public short getShort(String key) {
- unparcel();
- return getShort(key, (short) 0);
+ return super.getShort(key);
}
/**
@@ -956,18 +840,9 @@
* @param defaultValue Value to return if key does not exist
* @return a short value
*/
+ @Override
public short getShort(String key, short defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Short) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Short", defaultValue, e);
- return defaultValue;
- }
+ return super.getShort(key, defaultValue);
}
/**
@@ -977,9 +852,9 @@
* @param key a String
* @return an int value
*/
+ @Override
public int getInt(String key) {
- unparcel();
- return getInt(key, 0);
+ return super.getInt(key);
}
/**
@@ -990,18 +865,9 @@
* @param defaultValue Value to return if key does not exist
* @return an int value
*/
+ @Override
public int getInt(String key, int defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Integer) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Integer", defaultValue, e);
- return defaultValue;
- }
+ return super.getInt(key, defaultValue);
}
/**
@@ -1011,9 +877,9 @@
* @param key a String
* @return a long value
*/
+ @Override
public long getLong(String key) {
- unparcel();
- return getLong(key, 0L);
+ return super.getLong(key);
}
/**
@@ -1024,18 +890,9 @@
* @param defaultValue Value to return if key does not exist
* @return a long value
*/
+ @Override
public long getLong(String key, long defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Long) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Long", defaultValue, e);
- return defaultValue;
- }
+ return super.getLong(key, defaultValue);
}
/**
@@ -1045,9 +902,9 @@
* @param key a String
* @return a float value
*/
+ @Override
public float getFloat(String key) {
- unparcel();
- return getFloat(key, 0.0f);
+ return super.getFloat(key);
}
/**
@@ -1058,18 +915,9 @@
* @param defaultValue Value to return if key does not exist
* @return a float value
*/
+ @Override
public float getFloat(String key, float defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Float) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Float", defaultValue, e);
- return defaultValue;
- }
+ return super.getFloat(key, defaultValue);
}
/**
@@ -1079,9 +927,9 @@
* @param key a String
* @return a double value
*/
+ @Override
public double getDouble(String key) {
- unparcel();
- return getDouble(key, 0.0);
+ return super.getDouble(key);
}
/**
@@ -1092,18 +940,9 @@
* @param defaultValue Value to return if key does not exist
* @return a double value
*/
+ @Override
public double getDouble(String key, double defaultValue) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return defaultValue;
- }
- try {
- return (Double) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Double", defaultValue, e);
- return defaultValue;
- }
+ return super.getDouble(key, defaultValue);
}
/**
@@ -1114,15 +953,9 @@
* @param key a String, or null
* @return a String value, or null
*/
+ @Override
public String getString(String key) {
- unparcel();
- final Object o = mMap.get(key);
- try {
- return (String) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "String", e);
- return null;
- }
+ return super.getString(key);
}
/**
@@ -1134,9 +967,9 @@
* @return the String value associated with the given key, or defaultValue
* if no valid String object is currently mapped to that key.
*/
+ @Override
public String getString(String key, String defaultValue) {
- final String s = getString(key);
- return (s == null) ? defaultValue : s;
+ return super.getString(key, defaultValue);
}
/**
@@ -1147,15 +980,9 @@
* @param key a String, or null
* @return a CharSequence value, or null
*/
+ @Override
public CharSequence getCharSequence(String key) {
- unparcel();
- final Object o = mMap.get(key);
- try {
- return (CharSequence) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "CharSequence", e);
- return null;
- }
+ return super.getCharSequence(key);
}
/**
@@ -1167,9 +994,9 @@
* @return the CharSequence value associated with the given key, or defaultValue
* if no valid CharSequence object is currently mapped to that key.
*/
+ @Override
public CharSequence getCharSequence(String key, CharSequence defaultValue) {
- final CharSequence cs = getCharSequence(key);
- return (cs == null) ? defaultValue : cs;
+ return super.getCharSequence(key, defaultValue);
}
/**
@@ -1200,6 +1027,18 @@
* value is explicitly associated with the key.
*
* @param key a String, or null
+ * @return a PersistableBundle value, or null
+ */
+ public PersistableBundle getPersistableBundle(String key) {
+ return super.getPersistableBundle(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
* @return a Parcelable value, or null
*/
public <T extends Parcelable> T getParcelable(String key) {
@@ -1291,18 +1130,9 @@
* @param key a String, or null
* @return a Serializable value, or null
*/
+ @Override
public Serializable getSerializable(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (Serializable) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "Serializable", e);
- return null;
- }
+ return super.getSerializable(key);
}
/**
@@ -1313,18 +1143,9 @@
* @param key a String, or null
* @return an ArrayList<String> value, or null
*/
+ @Override
public ArrayList<Integer> getIntegerArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<Integer>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<Integer>", e);
- return null;
- }
+ return super.getIntegerArrayList(key);
}
/**
@@ -1335,18 +1156,9 @@
* @param key a String, or null
* @return an ArrayList<String> value, or null
*/
+ @Override
public ArrayList<String> getStringArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<String>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<String>", e);
- return null;
- }
+ return super.getStringArrayList(key);
}
/**
@@ -1357,18 +1169,9 @@
* @param key a String, or null
* @return an ArrayList<CharSequence> value, or null
*/
+ @Override
public ArrayList<CharSequence> getCharSequenceArrayList(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<CharSequence>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<CharSequence>", e);
- return null;
- }
+ return super.getCharSequenceArrayList(key);
}
/**
@@ -1379,18 +1182,9 @@
* @param key a String, or null
* @return a boolean[] value, or null
*/
+ @Override
public boolean[] getBooleanArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (boolean[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "byte[]", e);
- return null;
- }
+ return super.getBooleanArray(key);
}
/**
@@ -1401,18 +1195,9 @@
* @param key a String, or null
* @return a byte[] value, or null
*/
+ @Override
public byte[] getByteArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (byte[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "byte[]", e);
- return null;
- }
+ return super.getByteArray(key);
}
/**
@@ -1423,18 +1208,9 @@
* @param key a String, or null
* @return a short[] value, or null
*/
+ @Override
public short[] getShortArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (short[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "short[]", e);
- return null;
- }
+ return super.getShortArray(key);
}
/**
@@ -1445,18 +1221,9 @@
* @param key a String, or null
* @return a char[] value, or null
*/
+ @Override
public char[] getCharArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (char[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "char[]", e);
- return null;
- }
+ return super.getCharArray(key);
}
/**
@@ -1467,18 +1234,9 @@
* @param key a String, or null
* @return an int[] value, or null
*/
+ @Override
public int[] getIntArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (int[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "int[]", e);
- return null;
- }
+ return super.getIntArray(key);
}
/**
@@ -1489,18 +1247,9 @@
* @param key a String, or null
* @return a long[] value, or null
*/
+ @Override
public long[] getLongArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (long[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "long[]", e);
- return null;
- }
+ return super.getLongArray(key);
}
/**
@@ -1511,18 +1260,9 @@
* @param key a String, or null
* @return a float[] value, or null
*/
+ @Override
public float[] getFloatArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (float[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "float[]", e);
- return null;
- }
+ return super.getFloatArray(key);
}
/**
@@ -1533,18 +1273,9 @@
* @param key a String, or null
* @return a double[] value, or null
*/
+ @Override
public double[] getDoubleArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (double[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "double[]", e);
- return null;
- }
+ return super.getDoubleArray(key);
}
/**
@@ -1555,18 +1286,9 @@
* @param key a String, or null
* @return a String[] value, or null
*/
+ @Override
public String[] getStringArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (String[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "String[]", e);
- return null;
- }
+ return super.getStringArray(key);
}
/**
@@ -1577,18 +1299,9 @@
* @param key a String, or null
* @return a CharSequence[] value, or null
*/
+ @Override
public CharSequence[] getCharSequenceArray(String key) {
- unparcel();
- Object o = mMap.get(key);
- if (o == null) {
- return null;
- }
- try {
- return (CharSequence[]) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "CharSequence[]", e);
- return null;
- }
+ return super.getCharSequenceArray(key);
}
/**
@@ -1641,10 +1354,12 @@
public static final Parcelable.Creator<Bundle> CREATOR =
new Parcelable.Creator<Bundle>() {
+ @Override
public Bundle createFromParcel(Parcel in) {
return in.readBundle();
}
+ @Override
public Bundle[] newArray(int size) {
return new Bundle[size];
}
@@ -1653,6 +1368,7 @@
/**
* Report the nature of this Parcelable's contents
*/
+ @Override
public int describeContents() {
int mask = 0;
if (hasFileDescriptors()) {
@@ -1660,44 +1376,17 @@
}
return mask;
}
-
+
/**
* Writes the Bundle contents to a Parcel, typically in order for
* it to be passed through an IBinder connection.
* @param parcel The parcel to copy this bundle to.
*/
+ @Override
public void writeToParcel(Parcel parcel, int flags) {
final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
try {
- if (mParcelledData != null) {
- if (mParcelledData == EMPTY_PARCEL) {
- parcel.writeInt(0);
- } else {
- int length = mParcelledData.dataSize();
- parcel.writeInt(length);
- parcel.writeInt(BUNDLE_MAGIC);
- parcel.appendFrom(mParcelledData, 0, length);
- }
- } else {
- // Special case for empty bundles.
- if (mMap == null || mMap.size() <= 0) {
- parcel.writeInt(0);
- return;
- }
- int lengthPos = parcel.dataPosition();
- parcel.writeInt(-1); // dummy, will hold length
- parcel.writeInt(BUNDLE_MAGIC);
-
- int startPos = parcel.dataPosition();
- parcel.writeArrayMapInternal(mMap);
- int endPos = parcel.dataPosition();
-
- // Backpatch length
- parcel.setDataPosition(lengthPos);
- int length = endPos - startPos;
- parcel.writeInt(length);
- parcel.setDataPosition(endPos);
- }
+ super.writeToParcelInner(parcel, flags);
} finally {
parcel.restoreAllowFds(oldAllowFds);
}
@@ -1709,41 +1398,8 @@
* @param parcel The parcel to overwrite this bundle from.
*/
public void readFromParcel(Parcel parcel) {
- int length = parcel.readInt();
- if (length < 0) {
- throw new RuntimeException("Bad length in parcel: " + length);
- }
- readFromParcelInner(parcel, length);
- }
-
- void readFromParcelInner(Parcel parcel, int length) {
- if (length == 0) {
- // Empty Bundle or end of data.
- mParcelledData = EMPTY_PARCEL;
- mHasFds = false;
- mFdsKnown = true;
- return;
- }
- int magic = parcel.readInt();
- if (magic != BUNDLE_MAGIC) {
- //noinspection ThrowableInstanceNeverThrown
- throw new IllegalStateException("Bad magic number for Bundle: 0x"
- + Integer.toHexString(magic));
- }
-
- // Advance within this Parcel
- int offset = parcel.dataPosition();
- parcel.setDataPosition(offset + length);
-
- Parcel p = Parcel.obtain();
- p.setDataPosition(0);
- p.appendFrom(parcel, offset, length);
- if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
- + ": " + length + " bundle bytes starting at " + offset);
- p.setDataPosition(0);
-
- mParcelledData = p;
- mHasFds = p.hasFileDescriptors();
+ super.readFromParcelInner(parcel);
+ mHasFds = mParcelledData.hasFileDescriptors();
mFdsKnown = true;
}
@@ -1759,4 +1415,5 @@
}
return "Bundle[" + mMap.toString() + "]";
}
+
}
diff --git a/core/java/android/os/CommonBundle.java b/core/java/android/os/CommonBundle.java
new file mode 100644
index 0000000..e11f170
--- /dev/null
+++ b/core/java/android/os/CommonBundle.java
@@ -0,0 +1,1384 @@
+/*
+ * Copyright (C) 2014 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.os;
+
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A mapping from String values to various types.
+ */
+abstract class CommonBundle implements Parcelable, Cloneable {
+ private static final String TAG = "Bundle";
+ static final boolean DEBUG = false;
+
+ static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+ static final Parcel EMPTY_PARCEL;
+
+ static {
+ EMPTY_PARCEL = Parcel.obtain();
+ }
+
+ // Invariant - exactly one of mMap / mParcelledData will be null
+ // (except inside a call to unparcel)
+
+ ArrayMap<String, Object> mMap = null;
+
+ /*
+ * If mParcelledData is non-null, then mMap will be null and the
+ * data are stored as a Parcel containing a Bundle. When the data
+ * are unparcelled, mParcelledData willbe set to null.
+ */
+ Parcel mParcelledData = null;
+
+ /**
+ * The ClassLoader used when unparcelling data from mParcelledData.
+ */
+ private ClassLoader mClassLoader;
+
+ /**
+ * Constructs a new, empty Bundle that uses a specific ClassLoader for
+ * instantiating Parcelable and Serializable objects.
+ *
+ * @param loader An explicit ClassLoader to use when instantiating objects
+ * inside of the Bundle.
+ * @param capacity Initial size of the ArrayMap.
+ */
+ CommonBundle(ClassLoader loader, int capacity) {
+ mMap = capacity > 0 ?
+ new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>();
+ mClassLoader = loader == null ? getClass().getClassLoader() : loader;
+ }
+
+ /**
+ * Constructs a new, empty Bundle.
+ */
+ CommonBundle() {
+ this((ClassLoader) null, 0);
+ }
+
+ /**
+ * Constructs a Bundle whose data is stored as a Parcel. The data
+ * will be unparcelled on first contact, using the assigned ClassLoader.
+ *
+ * @param parcelledData a Parcel containing a Bundle
+ */
+ CommonBundle(Parcel parcelledData) {
+ readFromParcelInner(parcelledData);
+ }
+
+ CommonBundle(Parcel parcelledData, int length) {
+ readFromParcelInner(parcelledData, length);
+ }
+
+ /**
+ * Constructs a new, empty Bundle that uses a specific ClassLoader for
+ * instantiating Parcelable and Serializable objects.
+ *
+ * @param loader An explicit ClassLoader to use when instantiating objects
+ * inside of the Bundle.
+ */
+ CommonBundle(ClassLoader loader) {
+ this(loader, 0);
+ }
+
+ /**
+ * Constructs a new, empty Bundle sized to hold the given number of
+ * elements. The Bundle will grow as needed.
+ *
+ * @param capacity the initial capacity of the Bundle
+ */
+ CommonBundle(int capacity) {
+ this((ClassLoader) null, capacity);
+ }
+
+ /**
+ * Constructs a Bundle containing a copy of the mappings from the given
+ * Bundle.
+ *
+ * @param b a Bundle to be copied.
+ */
+ CommonBundle(CommonBundle b) {
+ if (b.mParcelledData != null) {
+ if (b.mParcelledData == EMPTY_PARCEL) {
+ mParcelledData = EMPTY_PARCEL;
+ } else {
+ mParcelledData = Parcel.obtain();
+ mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
+ mParcelledData.setDataPosition(0);
+ }
+ } else {
+ mParcelledData = null;
+ }
+
+ if (b.mMap != null) {
+ mMap = new ArrayMap<String, Object>(b.mMap);
+ } else {
+ mMap = null;
+ }
+
+ mClassLoader = b.mClassLoader;
+ }
+
+ /**
+ * TODO: optimize this later (getting just the value part of a Bundle
+ * with a single pair) once Bundle.forPair() above is implemented
+ * with a special single-value Map implementation/serialization.
+ *
+ * Note: value in single-pair Bundle may be null.
+ *
+ * @hide
+ */
+ String getPairValue() {
+ unparcel();
+ int size = mMap.size();
+ if (size > 1) {
+ Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
+ }
+ if (size == 0) {
+ return null;
+ }
+ Object o = mMap.valueAt(0);
+ try {
+ return (String) o;
+ } catch (ClassCastException e) {
+ typeWarning("getPairValue()", o, "String", e);
+ return null;
+ }
+ }
+
+ /**
+ * Changes the ClassLoader this Bundle uses when instantiating objects.
+ *
+ * @param loader An explicit ClassLoader to use when instantiating objects
+ * inside of the Bundle.
+ */
+ void setClassLoader(ClassLoader loader) {
+ mClassLoader = loader;
+ }
+
+ /**
+ * Return the ClassLoader currently associated with this Bundle.
+ */
+ ClassLoader getClassLoader() {
+ return mClassLoader;
+ }
+
+ /**
+ * If the underlying data are stored as a Parcel, unparcel them
+ * using the currently assigned class loader.
+ */
+ /* package */ synchronized void unparcel() {
+ if (mParcelledData == null) {
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + ": no parcelled data");
+ return;
+ }
+
+ if (mParcelledData == EMPTY_PARCEL) {
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + ": empty");
+ if (mMap == null) {
+ mMap = new ArrayMap<String, Object>(1);
+ } else {
+ mMap.erase();
+ }
+ mParcelledData = null;
+ return;
+ }
+
+ int N = mParcelledData.readInt();
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + ": reading " + N + " maps");
+ if (N < 0) {
+ return;
+ }
+ if (mMap == null) {
+ mMap = new ArrayMap<String, Object>(N);
+ } else {
+ mMap.erase();
+ mMap.ensureCapacity(N);
+ }
+ mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+ mParcelledData.recycle();
+ mParcelledData = null;
+ if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+ + " final map: " + mMap);
+ }
+
+ /**
+ * @hide
+ */
+ boolean isParcelled() {
+ return mParcelledData != null;
+ }
+
+ /**
+ * Returns the number of mappings contained in this Bundle.
+ *
+ * @return the number of mappings as an int.
+ */
+ int size() {
+ unparcel();
+ return mMap.size();
+ }
+
+ /**
+ * Returns true if the mapping of this Bundle is empty, false otherwise.
+ */
+ boolean isEmpty() {
+ unparcel();
+ return mMap.isEmpty();
+ }
+
+ /**
+ * Removes all elements from the mapping of this Bundle.
+ */
+ void clear() {
+ unparcel();
+ mMap.clear();
+ }
+
+ /**
+ * Returns true if the given key is contained in the mapping
+ * of this Bundle.
+ *
+ * @param key a String key
+ * @return true if the key is part of the mapping, false otherwise
+ */
+ boolean containsKey(String key) {
+ unparcel();
+ return mMap.containsKey(key);
+ }
+
+ /**
+ * Returns the entry with the given key as an object.
+ *
+ * @param key a String key
+ * @return an Object, or null
+ */
+ Object get(String key) {
+ unparcel();
+ return mMap.get(key);
+ }
+
+ /**
+ * Removes any entry with the given key from the mapping of this Bundle.
+ *
+ * @param key a String key
+ */
+ void remove(String key) {
+ unparcel();
+ mMap.remove(key);
+ }
+
+ /**
+ * Inserts all mappings from the given PersistableBundle into this CommonBundle.
+ *
+ * @param bundle a PersistableBundle
+ */
+ void putAll(PersistableBundle bundle) {
+ unparcel();
+ bundle.unparcel();
+ mMap.putAll(bundle.mMap);
+ }
+
+ /**
+ * Returns a Set containing the Strings used as keys in this Bundle.
+ *
+ * @return a Set of String keys
+ */
+ Set<String> keySet() {
+ unparcel();
+ return mMap.keySet();
+ }
+
+ /**
+ * Inserts a Boolean value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Boolean, or null
+ */
+ void putBoolean(String key, boolean value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a byte value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a byte
+ */
+ void putByte(String key, byte value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a char value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a char, or null
+ */
+ void putChar(String key, char value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a short value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a short
+ */
+ void putShort(String key, short value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts an int value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value an int, or null
+ */
+ void putInt(String key, int value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a long value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a long
+ */
+ void putLong(String key, long value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a float value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a float
+ */
+ void putFloat(String key, float value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a double value into the mapping of this Bundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a double
+ */
+ void putDouble(String key, double value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a String value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a String, or null
+ */
+ void putString(String key, String value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a CharSequence value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a CharSequence, or null
+ */
+ void putCharSequence(String key, CharSequence value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value an ArrayList<Integer> object, or null
+ */
+ void putIntegerArrayList(String key, ArrayList<Integer> value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value an ArrayList<String> object, or null
+ */
+ void putStringArrayList(String key, ArrayList<String> value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value an ArrayList<CharSequence> object, or null
+ */
+ void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a Serializable value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Serializable object, or null
+ */
+ void putSerializable(String key, Serializable value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a boolean array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a boolean array object, or null
+ */
+ void putBooleanArray(String key, boolean[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a byte array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a byte array object, or null
+ */
+ void putByteArray(String key, byte[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a short array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a short array object, or null
+ */
+ void putShortArray(String key, short[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a char array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a char array object, or null
+ */
+ void putCharArray(String key, char[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts an int array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value an int array object, or null
+ */
+ void putIntArray(String key, int[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a long array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a long array object, or null
+ */
+ void putLongArray(String key, long[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a float array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a float array object, or null
+ */
+ void putFloatArray(String key, float[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a double array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a double array object, or null
+ */
+ void putDoubleArray(String key, double[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a String array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a String array object, or null
+ */
+ void putStringArray(String key, String[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a CharSequence array value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a CharSequence array object, or null
+ */
+ void putCharSequenceArray(String key, CharSequence[] value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Bundle object, or null
+ */
+ void putPersistableBundle(String key, PersistableBundle value) {
+ unparcel();
+ mMap.put(key, value);
+ }
+
+ /**
+ * Returns the value associated with the given key, or false if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a boolean value
+ */
+ boolean getBoolean(String key) {
+ unparcel();
+ if (DEBUG) Log.d(TAG, "Getting boolean in "
+ + Integer.toHexString(System.identityHashCode(this)));
+ return getBoolean(key, false);
+ }
+
+ // Log a message if the value was non-null but not of the expected type
+ void typeWarning(String key, Object value, String className,
+ Object defaultValue, ClassCastException e) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Key ");
+ sb.append(key);
+ sb.append(" expected ");
+ sb.append(className);
+ sb.append(" but value was a ");
+ sb.append(value.getClass().getName());
+ sb.append(". The default value ");
+ sb.append(defaultValue);
+ sb.append(" was returned.");
+ Log.w(TAG, sb.toString());
+ Log.w(TAG, "Attempt to cast generated internal exception:", e);
+ }
+
+ void typeWarning(String key, Object value, String className,
+ ClassCastException e) {
+ typeWarning(key, value, className, "<null>", e);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a boolean value
+ */
+ boolean getBoolean(String key, boolean defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Boolean) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Boolean", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or (byte) 0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a byte value
+ */
+ byte getByte(String key) {
+ unparcel();
+ return getByte(key, (byte) 0);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a byte value
+ */
+ Byte getByte(String key, byte defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Byte) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Byte", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or (char) 0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a char value
+ */
+ char getChar(String key) {
+ unparcel();
+ return getChar(key, (char) 0);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a char value
+ */
+ char getChar(String key, char defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Character) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Character", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or (short) 0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a short value
+ */
+ short getShort(String key) {
+ unparcel();
+ return getShort(key, (short) 0);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a short value
+ */
+ short getShort(String key, short defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Short) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Short", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return an int value
+ */
+ int getInt(String key) {
+ unparcel();
+ return getInt(key, 0);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return an int value
+ */
+ int getInt(String key, int defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Integer) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Integer", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0L if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a long value
+ */
+ long getLong(String key) {
+ unparcel();
+ return getLong(key, 0L);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a long value
+ */
+ long getLong(String key, long defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Long) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Long", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0.0f if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a float value
+ */
+ float getFloat(String key) {
+ unparcel();
+ return getFloat(key, 0.0f);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a float value
+ */
+ float getFloat(String key, float defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Float) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Float", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0.0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a double value
+ */
+ double getDouble(String key) {
+ unparcel();
+ return getDouble(key, 0.0);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a double value
+ */
+ double getDouble(String key, double defaultValue) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return defaultValue;
+ }
+ try {
+ return (Double) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Double", defaultValue, e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a String value, or null
+ */
+ String getString(String key) {
+ unparcel();
+ final Object o = mMap.get(key);
+ try {
+ return (String) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "String", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String, or null
+ * @param defaultValue Value to return if key does not exist
+ * @return the String value associated with the given key, or defaultValue
+ * if no valid String object is currently mapped to that key.
+ */
+ String getString(String key, String defaultValue) {
+ final String s = getString(key);
+ return (s == null) ? defaultValue : s;
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a CharSequence value, or null
+ */
+ CharSequence getCharSequence(String key) {
+ unparcel();
+ final Object o = mMap.get(key);
+ try {
+ return (CharSequence) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "CharSequence", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String, or null
+ * @param defaultValue Value to return if key does not exist
+ * @return the CharSequence value associated with the given key, or defaultValue
+ * if no valid CharSequence object is currently mapped to that key.
+ */
+ CharSequence getCharSequence(String key, CharSequence defaultValue) {
+ final CharSequence cs = getCharSequence(key);
+ return (cs == null) ? defaultValue : cs;
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a Bundle value, or null
+ */
+ PersistableBundle getPersistableBundle(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (PersistableBundle) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Bundle", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a Serializable value, or null
+ */
+ Serializable getSerializable(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (Serializable) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "Serializable", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return an ArrayList<String> value, or null
+ */
+ ArrayList<Integer> getIntegerArrayList(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (ArrayList<Integer>) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "ArrayList<Integer>", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return an ArrayList<String> value, or null
+ */
+ ArrayList<String> getStringArrayList(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (ArrayList<String>) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "ArrayList<String>", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return an ArrayList<CharSequence> value, or null
+ */
+ ArrayList<CharSequence> getCharSequenceArrayList(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (ArrayList<CharSequence>) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "ArrayList<CharSequence>", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a boolean[] value, or null
+ */
+ boolean[] getBooleanArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (boolean[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "byte[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a byte[] value, or null
+ */
+ byte[] getByteArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (byte[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "byte[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a short[] value, or null
+ */
+ short[] getShortArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (short[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "short[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a char[] value, or null
+ */
+ char[] getCharArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (char[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "char[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return an int[] value, or null
+ */
+ int[] getIntArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (int[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "int[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a long[] value, or null
+ */
+ long[] getLongArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (long[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "long[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a float[] value, or null
+ */
+ float[] getFloatArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (float[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "float[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a double[] value, or null
+ */
+ double[] getDoubleArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (double[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "double[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a String[] value, or null
+ */
+ String[] getStringArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (String[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "String[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a CharSequence[] value, or null
+ */
+ CharSequence[] getCharSequenceArray(String key) {
+ unparcel();
+ Object o = mMap.get(key);
+ if (o == null) {
+ return null;
+ }
+ try {
+ return (CharSequence[]) o;
+ } catch (ClassCastException e) {
+ typeWarning(key, o, "CharSequence[]", e);
+ return null;
+ }
+ }
+
+ /**
+ * Writes the Bundle contents to a Parcel, typically in order for
+ * it to be passed through an IBinder connection.
+ * @param parcel The parcel to copy this bundle to.
+ */
+ void writeToParcelInner(Parcel parcel, int flags) {
+ if (mParcelledData != null) {
+ if (mParcelledData == EMPTY_PARCEL) {
+ parcel.writeInt(0);
+ } else {
+ int length = mParcelledData.dataSize();
+ parcel.writeInt(length);
+ parcel.writeInt(BUNDLE_MAGIC);
+ parcel.appendFrom(mParcelledData, 0, length);
+ }
+ } else {
+ // Special case for empty bundles.
+ if (mMap == null || mMap.size() <= 0) {
+ parcel.writeInt(0);
+ return;
+ }
+ int lengthPos = parcel.dataPosition();
+ parcel.writeInt(-1); // dummy, will hold length
+ parcel.writeInt(BUNDLE_MAGIC);
+
+ int startPos = parcel.dataPosition();
+ parcel.writeArrayMapInternal(mMap);
+ int endPos = parcel.dataPosition();
+
+ // Backpatch length
+ parcel.setDataPosition(lengthPos);
+ int length = endPos - startPos;
+ parcel.writeInt(length);
+ parcel.setDataPosition(endPos);
+ }
+ }
+
+ /**
+ * Reads the Parcel contents into this Bundle, typically in order for
+ * it to be passed through an IBinder connection.
+ * @param parcel The parcel to overwrite this bundle from.
+ */
+ void readFromParcelInner(Parcel parcel) {
+ int length = parcel.readInt();
+ if (length < 0) {
+ throw new RuntimeException("Bad length in parcel: " + length);
+ }
+ readFromParcelInner(parcel, length);
+ }
+
+ private void readFromParcelInner(Parcel parcel, int length) {
+ if (length == 0) {
+ // Empty Bundle or end of data.
+ mParcelledData = EMPTY_PARCEL;
+ return;
+ }
+ int magic = parcel.readInt();
+ if (magic != BUNDLE_MAGIC) {
+ //noinspection ThrowableInstanceNeverThrown
+ throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ + Integer.toHexString(magic));
+ }
+
+ // Advance within this Parcel
+ int offset = parcel.dataPosition();
+ parcel.setDataPosition(offset + length);
+
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ p.appendFrom(parcel, offset, length);
+ if (DEBUG) Log.d(TAG, "Retrieving " + Integer.toHexString(System.identityHashCode(this))
+ + ": " + length + " bundle bytes starting at " + offset);
+ p.setDataPosition(0);
+
+ mParcelledData = p;
+ }
+}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index e96398a..e98a26b 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -42,6 +42,7 @@
private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE";
private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
private static final String ENV_OEM_ROOT = "OEM_ROOT";
+ private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
/** {@hide} */
public static final String DIR_ANDROID = "Android";
@@ -57,6 +58,7 @@
private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
+ private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");
private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
@@ -225,6 +227,15 @@
}
/**
+ * Return root directory of the "vendor" partition that holds vendor-provided
+ * software that should persist across simple reflashing of the "system" partition.
+ * @hide
+ */
+ public static File getVendorDirectory() {
+ return DIR_VENDOR_ROOT;
+ }
+
+ /**
* Gets the system directory available for secure storage.
* If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
* Otherwise, it returns the unencrypted /data/system directory.
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index dc18dee..1089f27 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -370,8 +370,8 @@
* attacks.
*/
public static boolean contains(File dir, File file) {
- String dirPath = dir.getPath();
- String filePath = file.getPath();
+ String dirPath = dir.getAbsolutePath();
+ String filePath = file.getAbsolutePath();
if (dirPath.equals(filePath)) {
return true;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 8e0ff08..95cb9f3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -223,6 +223,7 @@
private static final int VAL_SPARSEBOOLEANARRAY = 22;
private static final int VAL_BOOLEANARRAY = 23;
private static final int VAL_CHARSEQUENCEARRAY = 24;
+ private static final int VAL_PERSISTABLEBUNDLE = 25;
// The initial int32 in a Binder call's reply Parcel header:
private static final int EX_SECURITY = -1;
@@ -638,6 +639,19 @@
}
/**
+ * Flatten a PersistableBundle into the parcel at the current dataPosition(),
+ * growing dataCapacity() if needed.
+ */
+ public final void writePersistableBundle(PersistableBundle val) {
+ if (val == null) {
+ writeInt(-1);
+ return;
+ }
+
+ val.writeToParcel(this, 0);
+ }
+
+ /**
* Flatten a List into the parcel at the current dataPosition(), growing
* dataCapacity() if needed. The List values are written using
* {@link #writeValue} and must follow the specification there.
@@ -1256,6 +1270,9 @@
} else if (v instanceof Byte) {
writeInt(VAL_BYTE);
writeInt((Byte) v);
+ } else if (v instanceof PersistableBundle) {
+ writeInt(VAL_PERSISTABLEBUNDLE);
+ writePersistableBundle((PersistableBundle) v);
} else {
Class<?> clazz = v.getClass();
if (clazz.isArray() && clazz.getComponentType() == Object.class) {
@@ -1633,6 +1650,35 @@
}
/**
+ * Read and return a new Bundle object from the parcel at the current
+ * dataPosition(). Returns null if the previously written Bundle object was
+ * null.
+ */
+ public final PersistableBundle readPersistableBundle() {
+ return readPersistableBundle(null);
+ }
+
+ /**
+ * Read and return a new Bundle object from the parcel at the current
+ * dataPosition(), using the given class loader to initialize the class
+ * loader of the Bundle for later retrieval of Parcelable objects.
+ * Returns null if the previously written Bundle object was null.
+ */
+ public final PersistableBundle readPersistableBundle(ClassLoader loader) {
+ int length = readInt();
+ if (length < 0) {
+ if (Bundle.DEBUG) Log.d(TAG, "null bundle: length=" + length);
+ return null;
+ }
+
+ final PersistableBundle bundle = new PersistableBundle(this, length);
+ if (loader != null) {
+ bundle.setClassLoader(loader);
+ }
+ return bundle;
+ }
+
+ /**
* Read and return a byte[] object from the parcel.
*/
public final byte[] createByteArray() {
@@ -2082,6 +2128,9 @@
case VAL_BUNDLE:
return readBundle(loader); // loading will be deferred
+ case VAL_PERSISTABLEBUNDLE:
+ return readPersistableBundle(loader);
+
default:
int off = dataPosition() - 4;
throw new RuntimeException(
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 86dc8b4..24bf05e 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -42,6 +42,7 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InterruptedIOException;
import java.net.DatagramSocket;
import java.net.Socket;
import java.nio.ByteOrder;
@@ -698,6 +699,9 @@
} catch (ErrnoException e) {
// Reporting status is best-effort
Log.w(TAG, "Failed to report status: " + e);
+ } catch (InterruptedIOException e) {
+ // Reporting status is best-effort
+ Log.w(TAG, "Failed to report status: " + e);
}
} finally {
@@ -728,6 +732,9 @@
Log.d(TAG, "Failed to read status; assuming dead: " + e);
return new Status(Status.DEAD);
}
+ } catch (InterruptedIOException e) {
+ Log.d(TAG, "Failed to read status; assuming dead: " + e);
+ return new Status(Status.DEAD);
}
}
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
new file mode 100644
index 0000000..c2cd3be
--- /dev/null
+++ b/core/java/android/os/PersistableBundle.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2014 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.os;
+
+import android.util.ArrayMap;
+
+import java.util.Set;
+
+/**
+ * A mapping from String values to various types that can be saved to persistent and later
+ * restored.
+ *
+ */
+public final class PersistableBundle extends CommonBundle {
+ public static final PersistableBundle EMPTY;
+ static final Parcel EMPTY_PARCEL;
+
+ static {
+ EMPTY = new PersistableBundle();
+ EMPTY.mMap = ArrayMap.EMPTY;
+ EMPTY_PARCEL = CommonBundle.EMPTY_PARCEL;
+ }
+
+ /**
+ * Constructs a new, empty PersistableBundle.
+ */
+ public PersistableBundle() {
+ super();
+ }
+
+ /**
+ * Constructs a PersistableBundle whose data is stored as a Parcel. The data
+ * will be unparcelled on first contact, using the assigned ClassLoader.
+ *
+ * @param parcelledData a Parcel containing a PersistableBundle
+ */
+ PersistableBundle(Parcel parcelledData) {
+ super(parcelledData);
+ }
+
+ /* package */ PersistableBundle(Parcel parcelledData, int length) {
+ super(parcelledData, length);
+ }
+
+ /**
+ * Constructs a new, empty PersistableBundle that uses a specific ClassLoader for
+ * instantiating Parcelable and Serializable objects.
+ *
+ * @param loader An explicit ClassLoader to use when instantiating objects
+ * inside of the PersistableBundle.
+ */
+ public PersistableBundle(ClassLoader loader) {
+ super(loader);
+ }
+
+ /**
+ * Constructs a new, empty PersistableBundle sized to hold the given number of
+ * elements. The PersistableBundle will grow as needed.
+ *
+ * @param capacity the initial capacity of the PersistableBundle
+ */
+ public PersistableBundle(int capacity) {
+ super(capacity);
+ }
+
+ /**
+ * Constructs a PersistableBundle containing a copy of the mappings from the given
+ * PersistableBundle.
+ *
+ * @param b a PersistableBundle to be copied.
+ */
+ public PersistableBundle(PersistableBundle b) {
+ super(b);
+ }
+
+ /**
+ * Make a PersistableBundle for a single key/value pair.
+ *
+ * @hide
+ */
+ public static PersistableBundle forPair(String key, String value) {
+ PersistableBundle b = new PersistableBundle(1);
+ b.putString(key, value);
+ return b;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public String getPairValue() {
+ return super.getPairValue();
+ }
+
+ /**
+ * Changes the ClassLoader this PersistableBundle uses when instantiating objects.
+ *
+ * @param loader An explicit ClassLoader to use when instantiating objects
+ * inside of the PersistableBundle.
+ */
+ @Override
+ public void setClassLoader(ClassLoader loader) {
+ super.setClassLoader(loader);
+ }
+
+ /**
+ * Return the ClassLoader currently associated with this PersistableBundle.
+ */
+ @Override
+ public ClassLoader getClassLoader() {
+ return super.getClassLoader();
+ }
+
+ /**
+ * Clones the current PersistableBundle. The internal map is cloned, but the keys and
+ * values to which it refers are copied by reference.
+ */
+ @Override
+ public Object clone() {
+ return new PersistableBundle(this);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isParcelled() {
+ return super.isParcelled();
+ }
+
+ /**
+ * Returns the number of mappings contained in this PersistableBundle.
+ *
+ * @return the number of mappings as an int.
+ */
+ @Override
+ public int size() {
+ return super.size();
+ }
+
+ /**
+ * Returns true if the mapping of this PersistableBundle is empty, false otherwise.
+ */
+ @Override
+ public boolean isEmpty() {
+ return super.isEmpty();
+ }
+
+ /**
+ * Removes all elements from the mapping of this PersistableBundle.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+
+ /**
+ * Returns true if the given key is contained in the mapping
+ * of this PersistableBundle.
+ *
+ * @param key a String key
+ * @return true if the key is part of the mapping, false otherwise
+ */
+ @Override
+ public boolean containsKey(String key) {
+ return super.containsKey(key);
+ }
+
+ /**
+ * Returns the entry with the given key as an object.
+ *
+ * @param key a String key
+ * @return an Object, or null
+ */
+ @Override
+ public Object get(String key) {
+ return super.get(key);
+ }
+
+ /**
+ * Removes any entry with the given key from the mapping of this PersistableBundle.
+ *
+ * @param key a String key
+ */
+ @Override
+ public void remove(String key) {
+ super.remove(key);
+ }
+
+ /**
+ * Inserts all mappings from the given PersistableBundle into this Bundle.
+ *
+ * @param bundle a PersistableBundle
+ */
+ public void putAll(PersistableBundle bundle) {
+ super.putAll(bundle);
+ }
+
+ /**
+ * Returns a Set containing the Strings used as keys in this PersistableBundle.
+ *
+ * @return a Set of String keys
+ */
+ @Override
+ public Set<String> keySet() {
+ return super.keySet();
+ }
+
+ /**
+ * Inserts an int value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value an int, or null
+ */
+ @Override
+ public void putInt(String key, int value) {
+ super.putInt(key, value);
+ }
+
+ /**
+ * Inserts a long value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a long
+ */
+ @Override
+ public void putLong(String key, long value) {
+ super.putLong(key, value);
+ }
+
+ /**
+ * Inserts a double value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key.
+ *
+ * @param key a String, or null
+ * @param value a double
+ */
+ @Override
+ public void putDouble(String key, double value) {
+ super.putDouble(key, value);
+ }
+
+ /**
+ * Inserts a String value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a String, or null
+ */
+ @Override
+ public void putString(String key, String value) {
+ super.putString(key, value);
+ }
+
+ /**
+ * Inserts an int array value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value an int array object, or null
+ */
+ @Override
+ public void putIntArray(String key, int[] value) {
+ super.putIntArray(key, value);
+ }
+
+ /**
+ * Inserts a long array value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a long array object, or null
+ */
+ @Override
+ public void putLongArray(String key, long[] value) {
+ super.putLongArray(key, value);
+ }
+
+ /**
+ * Inserts a double array value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a double array object, or null
+ */
+ @Override
+ public void putDoubleArray(String key, double[] value) {
+ super.putDoubleArray(key, value);
+ }
+
+ /**
+ * Inserts a String array value into the mapping of this PersistableBundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a String array object, or null
+ */
+ @Override
+ public void putStringArray(String key, String[] value) {
+ super.putStringArray(key, value);
+ }
+
+ /**
+ * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+ * any existing value for the given key. Either key or value may be null.
+ *
+ * @param key a String, or null
+ * @param value a Bundle object, or null
+ */
+ public void putPersistableBundle(String key, PersistableBundle value) {
+ super.putPersistableBundle(key, value);
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return an int value
+ */
+ @Override
+ public int getInt(String key) {
+ return super.getInt(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return an int value
+ */
+ @Override
+ public int getInt(String key, int defaultValue) {
+ return super.getInt(key, defaultValue);
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0L if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a long value
+ */
+ @Override
+ public long getLong(String key) {
+ return super.getLong(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a long value
+ */
+ @Override
+ public long getLong(String key, long defaultValue) {
+ return super.getLong(key, defaultValue);
+ }
+
+ /**
+ * Returns the value associated with the given key, or 0.0 if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @return a double value
+ */
+ @Override
+ public double getDouble(String key) {
+ return super.getDouble(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String
+ * @param defaultValue Value to return if key does not exist
+ * @return a double value
+ */
+ @Override
+ public double getDouble(String key, double defaultValue) {
+ return super.getDouble(key, defaultValue);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a String value, or null
+ */
+ @Override
+ public String getString(String key) {
+ return super.getString(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or defaultValue if
+ * no mapping of the desired type exists for the given key.
+ *
+ * @param key a String, or null
+ * @param defaultValue Value to return if key does not exist
+ * @return the String value associated with the given key, or defaultValue
+ * if no valid String object is currently mapped to that key.
+ */
+ @Override
+ public String getString(String key, String defaultValue) {
+ return super.getString(key, defaultValue);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a Bundle value, or null
+ */
+ @Override
+ public PersistableBundle getPersistableBundle(String key) {
+ return super.getPersistableBundle(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return an int[] value, or null
+ */
+ @Override
+ public int[] getIntArray(String key) {
+ return super.getIntArray(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a long[] value, or null
+ */
+ @Override
+ public long[] getLongArray(String key) {
+ return super.getLongArray(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a double[] value, or null
+ */
+ @Override
+ public double[] getDoubleArray(String key) {
+ return super.getDoubleArray(key);
+ }
+
+ /**
+ * Returns the value associated with the given key, or null if
+ * no mapping of the desired type exists for the given key or a null
+ * value is explicitly associated with the key.
+ *
+ * @param key a String, or null
+ * @return a String[] value, or null
+ */
+ @Override
+ public String[] getStringArray(String key) {
+ return super.getStringArray(key);
+ }
+
+ public static final Parcelable.Creator<PersistableBundle> CREATOR =
+ new Parcelable.Creator<PersistableBundle>() {
+ @Override
+ public PersistableBundle createFromParcel(Parcel in) {
+ return in.readPersistableBundle();
+ }
+
+ @Override
+ public PersistableBundle[] newArray(int size) {
+ return new PersistableBundle[size];
+ }
+ };
+
+ /**
+ * Report the nature of this Parcelable's contents
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Writes the PersistableBundle contents to a Parcel, typically in order for
+ * it to be passed through an IBinder connection.
+ * @param parcel The parcel to copy this bundle to.
+ */
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ final boolean oldAllowFds = parcel.pushAllowFds(false);
+ try {
+ super.writeToParcelInner(parcel, flags);
+ } finally {
+ parcel.restoreAllowFds(oldAllowFds);
+ }
+ }
+
+ /**
+ * Reads the Parcel contents into this PersistableBundle, typically in order for
+ * it to be passed through an IBinder connection.
+ * @param parcel The parcel to overwrite this bundle from.
+ */
+ public void readFromParcel(Parcel parcel) {
+ super.readFromParcelInner(parcel);
+ }
+
+ @Override
+ synchronized public String toString() {
+ if (mParcelledData != null) {
+ if (mParcelledData == EMPTY_PARCEL) {
+ return "PersistableBundle[EMPTY_PARCEL]";
+ } else {
+ return "PersistableBundle[mParcelledData.dataSize=" +
+ mParcelledData.dataSize() + "]";
+ }
+ }
+ return "PersistableBundle[" + mMap.toString() + "]";
+ }
+
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8aef9bd..7bac3af 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -300,7 +300,8 @@
/**
* Sets all the user-wide restrictions for this user.
- * Requires the MANAGE_USERS permission.
+ * Requires the MANAGE_USERS permission or profile/device owner
+ * privileges.
* @param restrictions the Bundle containing all the restrictions.
*/
public void setUserRestrictions(Bundle restrictions) {
@@ -309,7 +310,8 @@
/**
* Sets all the user-wide restrictions for the specified user.
- * Requires the MANAGE_USERS permission.
+ * Requires the MANAGE_USERS permission or profile/device owner
+ * privileges.
* @param restrictions the Bundle containing all the restrictions.
* @param userHandle the UserHandle of the user for whom to set the restrictions.
*/
@@ -323,7 +325,8 @@
/**
* Sets the value of a specific restriction.
- * Requires the MANAGE_USERS permission.
+ * Requires the MANAGE_USERS permission or profile/device owner
+ * privileges.
* @param key the key of the restriction
* @param value the value for the restriction
*/
@@ -336,7 +339,8 @@
/**
* @hide
* Sets the value of a specific restriction on a specific user.
- * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission or profile/device owner
+ * privileges.
* @param key the key of the restriction
* @param value the value for the restriction
* @param userHandle the user whose restriction is to be changed.
@@ -548,7 +552,7 @@
/**
* Returns information for all users on this device. Requires
* {@link android.Manifest.permission#MANAGE_USERS} permission.
- *
+ *
* @param excludeDying specify if the list should exclude users being
* removed.
* @return the list of users that were created.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index f0520b5..9a768e0 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -57,6 +57,10 @@
* <p>
* To create a document provider, extend {@link DocumentsProvider}, which
* provides a foundational implementation of this contract.
+ * <p>
+ * All client apps must hold a valid URI permission grant to access documents,
+ * typically issued when a user makes a selection through
+ * {@link Intent#ACTION_OPEN_DOCUMENT} or {@link Intent#ACTION_CREATE_DOCUMENT}.
*
* @see DocumentsProvider
*/
@@ -69,6 +73,8 @@
// content://com.example/root/sdcard/search/?query=pony
// content://com.example/document/12/
// content://com.example/document/12/children/
+ // content://com.example/via/12/document/24/
+ // content://com.example/via/12/document/24/children/
private DocumentsContract() {
}
@@ -425,6 +431,14 @@
public static final int FLAG_SUPPORTS_SEARCH = 1 << 3;
/**
+ * Flag indicating that this root supports directory selection.
+ *
+ * @see #COLUMN_FLAGS
+ * @see DocumentsProvider#isChildDocument(String, String)
+ */
+ public static final int FLAG_SUPPORTS_DIR_SELECTION = 1 << 4;
+
+ /**
* Flag indicating that this root is currently empty. This may be used
* to hide the root when opening documents, but the root will still be
* shown when creating documents and {@link #FLAG_SUPPORTS_CREATE} is
@@ -484,12 +498,15 @@
/** {@hide} */
public static final String EXTRA_THUMBNAIL_SIZE = "thumbnail_size";
+ /** {@hide} */
+ public static final String EXTRA_URI = "uri";
private static final String PATH_ROOT = "root";
private static final String PATH_RECENT = "recent";
private static final String PATH_DOCUMENT = "document";
private static final String PATH_CHILDREN = "children";
private static final String PATH_SEARCH = "search";
+ private static final String PATH_VIA = "via";
private static final String PARAM_QUERY = "query";
private static final String PARAM_MANAGE = "manage";
@@ -532,6 +549,17 @@
}
/**
+ * Build URI representing access to descendant documents of the given
+ * {@link Document#COLUMN_DOCUMENT_ID}.
+ *
+ * @see #getViaDocumentId(Uri)
+ */
+ public static Uri buildViaUri(String authority, String documentId) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority)
+ .appendPath(PATH_VIA).appendPath(documentId).build();
+ }
+
+ /**
* Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a
* document provider. When queried, a provider will return a single row with
* columns defined by {@link Document}.
@@ -545,6 +573,41 @@
}
/**
+ * Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a
+ * document provider. Instead of directly accessing the target document,
+ * gain access via another document. The target document must be a
+ * descendant (child, grandchild, etc) of the via document.
+ * <p>
+ * This is typically used to access documents under a user-selected
+ * directory, since it doesn't require the user to separately confirm each
+ * new document access.
+ *
+ * @param viaUri a related document (directory) that the caller is
+ * leveraging to gain access to the target document. The target
+ * document must be a descendant of this directory.
+ * @param documentId the target document, which the caller may not have
+ * direct access to.
+ * @see Intent#ACTION_PICK_DIRECTORY
+ * @see DocumentsProvider#isChildDocument(String, String)
+ * @see #buildDocumentUri(String, String)
+ */
+ public static Uri buildDocumentViaUri(Uri viaUri, String documentId) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(viaUri.getAuthority()).appendPath(PATH_VIA)
+ .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT)
+ .appendPath(documentId).build();
+ }
+
+ /** {@hide} */
+ public static Uri buildDocumentMaybeViaUri(Uri baseUri, String documentId) {
+ if (isViaUri(baseUri)) {
+ return buildDocumentViaUri(baseUri, documentId);
+ } else {
+ return buildDocumentUri(baseUri.getAuthority(), documentId);
+ }
+ }
+
+ /**
* Build URI representing the children of the given directory in a document
* provider. When queried, a provider will return zero or more rows with
* columns defined by {@link Document}.
@@ -562,6 +625,32 @@
}
/**
+ * Build URI representing the children of the given directory in a document
+ * provider. Instead of directly accessing the target document, gain access
+ * via another document. The target document must be a descendant (child,
+ * grandchild, etc) of the via document.
+ * <p>
+ * This is typically used to access documents under a user-selected
+ * directory, since it doesn't require the user to separately confirm each
+ * new document access.
+ *
+ * @param viaUri a related document (directory) that the caller is
+ * leveraging to gain access to the target document. The target
+ * document must be a descendant of this directory.
+ * @param parentDocumentId the target document, which the caller may not
+ * have direct access to.
+ * @see Intent#ACTION_PICK_DIRECTORY
+ * @see DocumentsProvider#isChildDocument(String, String)
+ * @see #buildChildDocumentsUri(String, String)
+ */
+ public static Uri buildChildDocumentsViaUri(Uri viaUri, String parentDocumentId) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(viaUri.getAuthority()).appendPath(PATH_VIA)
+ .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT)
+ .appendPath(parentDocumentId).appendPath(PATH_CHILDREN).build();
+ }
+
+ /**
* Build URI representing a search for matching documents under a specific
* root in a document provider. When queried, a provider will return zero or
* more rows with columns defined by {@link Document}.
@@ -580,21 +669,31 @@
/**
* Test if the given URI represents a {@link Document} backed by a
* {@link DocumentsProvider}.
+ *
+ * @see #buildDocumentUri(String, String)
+ * @see #buildDocumentViaUri(Uri, String)
*/
public static boolean isDocumentUri(Context context, Uri uri) {
final List<String> paths = uri.getPathSegments();
- if (paths.size() < 2) {
- return false;
+ if (paths.size() >= 2
+ && (PATH_DOCUMENT.equals(paths.get(0)) || PATH_VIA.equals(paths.get(0)))) {
+ return isDocumentsProvider(context, uri.getAuthority());
}
- if (!PATH_DOCUMENT.equals(paths.get(0))) {
- return false;
- }
+ return false;
+ }
+ /** {@hide} */
+ public static boolean isViaUri(Uri uri) {
+ final List<String> paths = uri.getPathSegments();
+ return (paths.size() >= 2 && PATH_VIA.equals(paths.get(0)));
+ }
+
+ private static boolean isDocumentsProvider(Context context, String authority) {
final Intent intent = new Intent(PROVIDER_INTERFACE);
final List<ResolveInfo> infos = context.getPackageManager()
.queryIntentContentProviders(intent, 0);
for (ResolveInfo info : infos) {
- if (uri.getAuthority().equals(info.providerInfo.authority)) {
+ if (authority.equals(info.providerInfo.authority)) {
return true;
}
}
@@ -606,27 +705,40 @@
*/
public static String getRootId(Uri rootUri) {
final List<String> paths = rootUri.getPathSegments();
- if (paths.size() < 2) {
- throw new IllegalArgumentException("Not a root: " + rootUri);
+ if (paths.size() >= 2 && PATH_ROOT.equals(paths.get(0))) {
+ return paths.get(1);
}
- if (!PATH_ROOT.equals(paths.get(0))) {
- throw new IllegalArgumentException("Not a root: " + rootUri);
- }
- return paths.get(1);
+ throw new IllegalArgumentException("Invalid URI: " + rootUri);
}
/**
* Extract the {@link Document#COLUMN_DOCUMENT_ID} from the given URI.
+ *
+ * @see #isDocumentUri(Context, Uri)
*/
public static String getDocumentId(Uri documentUri) {
final List<String> paths = documentUri.getPathSegments();
- if (paths.size() < 2) {
- throw new IllegalArgumentException("Not a document: " + documentUri);
+ if (paths.size() >= 2 && PATH_DOCUMENT.equals(paths.get(0))) {
+ return paths.get(1);
}
- if (!PATH_DOCUMENT.equals(paths.get(0))) {
- throw new IllegalArgumentException("Not a document: " + documentUri);
+ if (paths.size() >= 4 && PATH_VIA.equals(paths.get(0))
+ && PATH_DOCUMENT.equals(paths.get(2))) {
+ return paths.get(3);
}
- return paths.get(1);
+ throw new IllegalArgumentException("Invalid URI: " + documentUri);
+ }
+
+ /**
+ * Extract the via {@link Document#COLUMN_DOCUMENT_ID} from the given URI.
+ *
+ * @see #isViaUri(Uri)
+ */
+ public static String getViaDocumentId(Uri documentUri) {
+ final List<String> paths = documentUri.getPathSegments();
+ if (paths.size() >= 2 && PATH_VIA.equals(paths.get(0))) {
+ return paths.get(1);
+ }
+ throw new IllegalArgumentException("Invalid URI: " + documentUri);
}
/**
@@ -758,7 +870,6 @@
* @param mimeType MIME type of new document
* @param displayName name of new document
* @return newly created document, or {@code null} if failed
- * @hide
*/
public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
String mimeType, String displayName) {
@@ -778,13 +889,12 @@
public static Uri createDocument(ContentProviderClient client, Uri parentDocumentUri,
String mimeType, String displayName) throws RemoteException {
final Bundle in = new Bundle();
- in.putString(Document.COLUMN_DOCUMENT_ID, getDocumentId(parentDocumentUri));
+ in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
in.putString(Document.COLUMN_MIME_TYPE, mimeType);
in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
final Bundle out = client.call(METHOD_CREATE_DOCUMENT, null, in);
- return buildDocumentUri(
- parentDocumentUri.getAuthority(), out.getString(Document.COLUMN_DOCUMENT_ID));
+ return out.getParcelable(DocumentsContract.EXTRA_URI);
}
/**
@@ -811,7 +921,7 @@
public static void deleteDocument(ContentProviderClient client, Uri documentUri)
throws RemoteException {
final Bundle in = new Bundle();
- in.putString(Document.COLUMN_DOCUMENT_ID, getDocumentId(documentUri));
+ in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
client.call(METHOD_DELETE_DOCUMENT, null, in);
}
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 49816f8..1a7a00f2 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -46,6 +46,7 @@
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
+import java.util.Objects;
/**
* Base class for a document provider. A document provider offers read and write
@@ -125,6 +126,8 @@
private static final int MATCH_SEARCH = 4;
private static final int MATCH_DOCUMENT = 5;
private static final int MATCH_CHILDREN = 6;
+ private static final int MATCH_DOCUMENT_VIA = 7;
+ private static final int MATCH_CHILDREN_VIA = 8;
private String mAuthority;
@@ -144,6 +147,8 @@
mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
+ mMatcher.addURI(mAuthority, "via/*/document/*", MATCH_DOCUMENT_VIA);
+ mMatcher.addURI(mAuthority, "via/*/document/*/children", MATCH_CHILDREN_VIA);
// Sanity check our setup
if (!info.exported) {
@@ -161,6 +166,35 @@
}
/**
+ * Test if a document is descendant (child, grandchild, etc) from the given
+ * parent. Providers must override this to support directory selection. You
+ * should avoid making network requests to keep this request fast.
+ *
+ * @param parentDocumentId parent to verify against.
+ * @param documentId child to verify.
+ * @return if given document is a descendant of the given parent.
+ * @see DocumentsContract.Root#FLAG_SUPPORTS_DIR_SELECTION
+ */
+ public boolean isChildDocument(String parentDocumentId, String documentId) {
+ return false;
+ }
+
+ /** {@hide} */
+ private void enforceVia(Uri documentUri) {
+ if (DocumentsContract.isViaUri(documentUri)) {
+ final String parent = DocumentsContract.getViaDocumentId(documentUri);
+ final String child = DocumentsContract.getDocumentId(documentUri);
+ if (Objects.equals(parent, child)) {
+ return;
+ }
+ if (!isChildDocument(parent, child)) {
+ throw new SecurityException(
+ "Document " + child + " is not a descendant of " + parent);
+ }
+ }
+ }
+
+ /**
* Create a new document and return its newly generated
* {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
* {@link Document#COLUMN_DOCUMENT_ID} to represent the document, which must
@@ -182,9 +216,10 @@
/**
* Delete the requested document. Upon returning, any URI permission grants
- * for the requested document will be revoked. If additional documents were
- * deleted as a side effect of this call, such as documents inside a
- * directory, the implementor is responsible for revoking those permissions.
+ * for the given document will be revoked. If additional documents were
+ * deleted as a side effect of this call (such as documents inside a
+ * directory) the implementor is responsible for revoking those permissions
+ * using {@link #revokeDocumentPermission(String)}.
*
* @param documentId the document to delete.
*/
@@ -420,8 +455,12 @@
return querySearchDocuments(
getRootId(uri), getSearchDocumentsQuery(uri), projection);
case MATCH_DOCUMENT:
+ case MATCH_DOCUMENT_VIA:
+ enforceVia(uri);
return queryDocument(getDocumentId(uri), projection);
case MATCH_CHILDREN:
+ case MATCH_CHILDREN_VIA:
+ enforceVia(uri);
if (DocumentsContract.isManageMode(uri)) {
return queryChildDocumentsForManage(
getDocumentId(uri), projection, sortOrder);
@@ -449,6 +488,8 @@
case MATCH_ROOT:
return DocumentsContract.Root.MIME_TYPE_ITEM;
case MATCH_DOCUMENT:
+ case MATCH_DOCUMENT_VIA:
+ enforceVia(uri);
return getDocumentType(getDocumentId(uri));
default:
return null;
@@ -460,6 +501,49 @@
}
/**
+ * Implementation is provided by the parent class. Can be overridden to
+ * provide additional functionality, but subclasses <em>must</em> always
+ * call the superclass. If the superclass returns {@code null}, the subclass
+ * may implement custom behavior.
+ * <p>
+ * This is typically used to resolve a "via" URI into a concrete document
+ * reference, issuing a narrower single-document URI permission grant along
+ * the way.
+ *
+ * @see DocumentsContract#buildDocumentViaUri(Uri, String)
+ */
+ @Override
+ public Uri canonicalize(Uri uri) {
+ final Context context = getContext();
+ switch (mMatcher.match(uri)) {
+ case MATCH_DOCUMENT_VIA:
+ enforceVia(uri);
+
+ final Uri narrowUri = DocumentsContract.buildDocumentUri(uri.getAuthority(),
+ DocumentsContract.getDocumentId(uri));
+
+ // Caller may only have prefix grant, so extend them a grant to
+ // the narrow Uri. Caller already holds read grant to get here,
+ // so check for any other modes we should extend.
+ int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
+ if (context.checkCallingOrSelfUriPermission(uri,
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED) {
+ modeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+ }
+ if (context.checkCallingOrSelfUriPermission(uri,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
+ == PackageManager.PERMISSION_GRANTED) {
+ modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
+ }
+ context.grantUriPermission(getCallingPackage(), narrowUri, modeFlags);
+ return narrowUri;
+ }
+ return null;
+ }
+
+ /**
* Implementation is provided by the parent class. Throws by default, and
* cannot be overriden.
*
@@ -496,54 +580,47 @@
* provide additional functionality, but subclasses <em>must</em> always
* call the superclass. If the superclass returns {@code null}, the subclass
* may implement custom behavior.
- *
- * @see #openDocument(String, String, CancellationSignal)
- * @see #deleteDocument(String)
*/
@Override
public Bundle call(String method, String arg, Bundle extras) {
- final Context context = getContext();
-
if (!method.startsWith("android:")) {
- // Let non-platform methods pass through
+ // Ignore non-platform methods
return super.call(method, arg, extras);
}
- final String documentId = extras.getString(Document.COLUMN_DOCUMENT_ID);
- final Uri documentUri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
+ final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+ final String authority = documentUri.getAuthority();
+ final String documentId = DocumentsContract.getDocumentId(documentUri);
- // Require that caller can manage requested document
- final boolean callerHasManage =
- context.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DOCUMENTS)
- == PackageManager.PERMISSION_GRANTED;
- enforceWritePermissionInner(documentUri);
+ if (!mAuthority.equals(authority)) {
+ throw new SecurityException(
+ "Requested authority " + authority + " doesn't match provider " + mAuthority);
+ }
+ enforceVia(documentUri);
final Bundle out = new Bundle();
try {
if (METHOD_CREATE_DOCUMENT.equals(method)) {
+ enforceWritePermissionInner(documentUri);
+
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = createDocument(documentId, mimeType, displayName);
- out.putString(Document.COLUMN_DOCUMENT_ID, newDocumentId);
- // Extend permission grant towards caller if needed
- if (!callerHasManage) {
- final Uri newDocumentUri = DocumentsContract.buildDocumentUri(
- mAuthority, newDocumentId);
- context.grantUriPermission(getCallingPackage(), newDocumentUri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
- }
+ // No need to issue new grants here, since caller either has
+ // manage permission or a prefix grant. We might generate a
+ // "via" style URI if that's how they called us.
+ final Uri newDocumentUri = DocumentsContract.buildDocumentMaybeViaUri(documentUri,
+ newDocumentId);
+ out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_DELETE_DOCUMENT.equals(method)) {
+ enforceWritePermissionInner(documentUri);
deleteDocument(documentId);
// Document no longer exists, clean up any grants
- context.revokeUriPermission(documentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+ revokeDocumentPermission(documentId);
} else {
throw new UnsupportedOperationException("Method not supported " + method);
@@ -555,12 +632,25 @@
}
/**
+ * Revoke any active permission grants for the given
+ * {@link Document#COLUMN_DOCUMENT_ID}, usually called when a document
+ * becomes invalid. Follows the same semantics as
+ * {@link Context#revokeUriPermission(Uri, int)}.
+ */
+ public final void revokeDocumentPermission(String documentId) {
+ final Context context = getContext();
+ context.revokeUriPermission(DocumentsContract.buildDocumentUri(mAuthority, documentId), ~0);
+ context.revokeUriPermission(DocumentsContract.buildViaUri(mAuthority, documentId), ~0);
+ }
+
+ /**
* Implementation is provided by the parent class. Cannot be overriden.
*
* @see #openDocument(String, String, CancellationSignal)
*/
@Override
public final ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ enforceVia(uri);
return openDocument(getDocumentId(uri), mode, null);
}
@@ -572,17 +662,47 @@
@Override
public final ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
throws FileNotFoundException {
+ enforceVia(uri);
return openDocument(getDocumentId(uri), mode, signal);
}
/**
* Implementation is provided by the parent class. Cannot be overriden.
*
+ * @see #openDocument(String, String, CancellationSignal)
+ */
+ @Override
+ @SuppressWarnings("resource")
+ public final AssetFileDescriptor openAssetFile(Uri uri, String mode)
+ throws FileNotFoundException {
+ enforceVia(uri);
+ final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, null);
+ return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
+ }
+
+ /**
+ * Implementation is provided by the parent class. Cannot be overriden.
+ *
+ * @see #openDocument(String, String, CancellationSignal)
+ */
+ @Override
+ @SuppressWarnings("resource")
+ public final AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ enforceVia(uri);
+ final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, signal);
+ return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
+ }
+
+ /**
+ * Implementation is provided by the parent class. Cannot be overriden.
+ *
* @see #openDocumentThumbnail(String, Point, CancellationSignal)
*/
@Override
public final AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
throws FileNotFoundException {
+ enforceVia(uri);
if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
return openDocumentThumbnail(getDocumentId(uri), sizeHint, null);
@@ -600,6 +720,7 @@
public final AssetFileDescriptor openTypedAssetFile(
Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
throws FileNotFoundException {
+ enforceVia(uri);
if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
return openDocumentThumbnail(getDocumentId(uri), sizeHint, signal);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1e202ca..7f9f862 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5970,6 +5970,12 @@
public static final String SHOW_PROCESSES = "show_processes";
/**
+ * If 1 low power mode is enabled.
+ * @hide
+ */
+ public static final String LOW_POWER_MODE = "low_power";
+
+ /**
* If 1, the activity manager will aggressively finish activities and
* processes as soon as they are no longer needed. If 0, the normal
* extended lifetime is used.
@@ -6120,6 +6126,13 @@
}
/**
+ * Opaque value, changes when persisted zen mode configuration changes.
+ *
+ * @hide
+ */
+ public static final String ZEN_MODE_CONFIG_ETAG = "zen_mode_config_etag";
+
+ /**
* Defines global heads up toggle. One of HEADS_UP_OFF, HEADS_UP_ON.
*
* @hide
diff --git a/core/java/android/service/notification/ZenModeConfig.aidl b/core/java/android/service/notification/ZenModeConfig.aidl
new file mode 100644
index 0000000..c73b75e
--- /dev/null
+++ b/core/java/android/service/notification/ZenModeConfig.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014, 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.service.notification;
+
+parcelable ZenModeConfig;
+
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
new file mode 100644
index 0000000..925ddcf
--- /dev/null
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright (c) 2014, 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.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Persisted configuration for zen mode.
+ *
+ * @hide
+ */
+public class ZenModeConfig implements Parcelable {
+
+ public static final String SLEEP_MODE_NIGHTS = "nights";
+ public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights";
+
+ private static final int XML_VERSION = 1;
+ private static final String ZEN_TAG = "zen";
+ private static final String ZEN_ATT_VERSION = "version";
+ private static final String ALLOW_TAG = "allow";
+ private static final String ALLOW_ATT_CALLS = "calls";
+ private static final String ALLOW_ATT_MESSAGES = "messages";
+ private static final String SLEEP_TAG = "sleep";
+ private static final String SLEEP_ATT_MODE = "mode";
+
+ private static final String SLEEP_ATT_START_HR = "startHour";
+ private static final String SLEEP_ATT_START_MIN = "startMin";
+ private static final String SLEEP_ATT_END_HR = "endHour";
+ private static final String SLEEP_ATT_END_MIN = "endMin";
+
+ public boolean allowCalls;
+ public boolean allowMessages;
+
+ public String sleepMode;
+ public int sleepStartHour;
+ public int sleepStartMinute;
+ public int sleepEndHour;
+ public int sleepEndMinute;
+
+ public ZenModeConfig() { }
+
+ public ZenModeConfig(Parcel source) {
+ allowCalls = source.readInt() == 1;
+ allowMessages = source.readInt() == 1;
+ if (source.readInt() == 1) {
+ sleepMode = source.readString();
+ }
+ sleepStartHour = source.readInt();
+ sleepStartMinute = source.readInt();
+ sleepEndHour = source.readInt();
+ sleepEndMinute = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(allowCalls ? 1 : 0);
+ dest.writeInt(allowMessages ? 1 : 0);
+ if (sleepMode != null) {
+ dest.writeInt(1);
+ dest.writeString(sleepMode);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(sleepStartHour);
+ dest.writeInt(sleepStartMinute);
+ dest.writeInt(sleepEndHour);
+ dest.writeInt(sleepEndMinute);
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
+ .append("allowCalls=").append(allowCalls)
+ .append(",allowMessages=").append(allowMessages)
+ .append(",sleepMode=").append(sleepMode)
+ .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
+ .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
+ .append(']').toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ZenModeConfig)) return false;
+ if (o == this) return true;
+ final ZenModeConfig other = (ZenModeConfig) o;
+ return other.allowCalls == allowCalls
+ && other.allowMessages == allowMessages
+ && Objects.equals(other.sleepMode, sleepMode)
+ && other.sleepStartHour == sleepStartHour
+ && other.sleepStartMinute == sleepStartMinute
+ && other.sleepEndHour == sleepEndHour
+ && other.sleepEndMinute == sleepEndMinute;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(allowCalls, allowMessages, sleepMode, sleepStartHour,
+ sleepStartMinute, sleepEndHour, sleepEndMinute);
+ }
+
+ public boolean isValid() {
+ return isValidHour(sleepStartHour) && isValidMinute(sleepStartMinute)
+ && isValidHour(sleepEndHour) && isValidMinute(sleepEndMinute)
+ && (sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS)
+ || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS));
+ }
+
+ public static ZenModeConfig readXml(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type = parser.getEventType();
+ if (type != XmlPullParser.START_TAG) return null;
+ String tag = parser.getName();
+ if (!ZEN_TAG.equals(tag)) return null;
+ final ZenModeConfig rt = new ZenModeConfig();
+ final int version = Integer.parseInt(parser.getAttributeValue(null, ZEN_ATT_VERSION));
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ tag = parser.getName();
+ if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) return rt;
+ if (type == XmlPullParser.START_TAG) {
+ if (ALLOW_TAG.equals(tag)) {
+ rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
+ rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+ } else if (SLEEP_TAG.equals(tag)) {
+ final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE);
+ rt.sleepMode = (SLEEP_MODE_NIGHTS.equals(mode)
+ || SLEEP_MODE_WEEKNIGHTS.equals(mode)) ? mode : null;
+ final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0);
+ final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0);
+ final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0);
+ final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0);
+ rt.sleepStartHour = isValidHour(startHour) ? startHour : 0;
+ rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0;
+ rt.sleepEndHour = isValidHour(endHour) ? endHour : 0;
+ rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0;
+ }
+ }
+ }
+ return rt;
+ }
+
+ public void writeXml(XmlSerializer out) throws IOException {
+ out.startTag(null, ZEN_TAG);
+ out.attribute(null, ZEN_ATT_VERSION, Integer.toString(XML_VERSION));
+
+ out.startTag(null, ALLOW_TAG);
+ out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls));
+ out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages));
+ out.endTag(null, ALLOW_TAG);
+
+ out.startTag(null, SLEEP_TAG);
+ if (sleepMode != null) {
+ out.attribute(null, SLEEP_ATT_MODE, sleepMode);
+ }
+ out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour));
+ out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute));
+ out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour));
+ out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute));
+ out.endTag(null, SLEEP_TAG);
+
+ out.endTag(null, ZEN_TAG);
+ }
+
+ public static boolean isValidHour(int val) {
+ return val >= 0 && val < 24;
+ }
+
+ public static boolean isValidMinute(int val) {
+ return val >= 0 && val < 60;
+ }
+
+ private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) {
+ final String val = parser.getAttributeValue(null, att);
+ if (TextUtils.isEmpty(val)) return defValue;
+ return Boolean.valueOf(val);
+ }
+
+ private static int safeInt(XmlPullParser parser, String att, int defValue) {
+ final String val = parser.getAttributeValue(null, att);
+ if (TextUtils.isEmpty(val)) return defValue;
+ return Integer.valueOf(val);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public ZenModeConfig copy() {
+ final Parcel parcel = Parcel.obtain();
+ try {
+ writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return new ZenModeConfig(parcel);
+ } finally {
+ parcel.recycle();
+ }
+ }
+
+ public static final Parcelable.Creator<ZenModeConfig> CREATOR
+ = new Parcelable.Creator<ZenModeConfig>() {
+ @Override
+ public ZenModeConfig createFromParcel(Parcel source) {
+ return new ZenModeConfig(source);
+ }
+
+ @Override
+ public ZenModeConfig[] newArray(int size) {
+ return new ZenModeConfig[size];
+ }
+ };
+}
diff --git a/core/java/android/tv/ITvInputManager.aidl b/core/java/android/tv/ITvInputManager.aidl
index a927dc9..a4c99e4 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/core/java/android/tv/ITvInputManager.aidl
@@ -17,6 +17,7 @@
package android.tv;
import android.content.ComponentName;
+import android.graphics.Rect;
import android.net.Uri;
import android.tv.ITvInputClient;
import android.tv.TvInputInfo;
@@ -40,4 +41,9 @@
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
void setVolume(in IBinder sessionToken, float volume, int userId);
void tune(in IBinder sessionToken, in Uri channelUri, int userId);
+
+ void createOverlayView(in IBinder sessionToken, in IBinder windowToken, in Rect frame,
+ int userId);
+ void relayoutOverlayView(in IBinder sessionToken, in Rect frame, int userId);
+ void removeOverlayView(in IBinder sessionToken, int userId);
}
diff --git a/core/java/android/tv/ITvInputService.aidl b/core/java/android/tv/ITvInputService.aidl
index d80f286..672784f 100644
--- a/core/java/android/tv/ITvInputService.aidl
+++ b/core/java/android/tv/ITvInputService.aidl
@@ -17,7 +17,6 @@
package android.tv;
import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSession;
import android.tv.ITvInputSessionCallback;
/**
diff --git a/core/java/android/tv/ITvInputSession.aidl b/core/java/android/tv/ITvInputSession.aidl
index d379d2d..32fee4b 100644
--- a/core/java/android/tv/ITvInputSession.aidl
+++ b/core/java/android/tv/ITvInputSession.aidl
@@ -16,6 +16,7 @@
package android.tv;
+import android.graphics.Rect;
import android.net.Uri;
import android.view.Surface;
@@ -31,4 +32,8 @@
// is to introduce some new concepts that will solve a number of problems in audio policy today.
void setVolume(float volume);
void tune(in Uri channelUri);
+
+ void createOverlayView(in IBinder windowToken, in Rect frame);
+ void relayoutOverlayView(in Rect frame);
+ void removeOverlayView();
}
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/core/java/android/tv/ITvInputSessionWrapper.java
index 66fe5e1..a6e0877 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/core/java/android/tv/ITvInputSessionWrapper.java
@@ -17,13 +17,16 @@
package android.tv;
import android.content.Context;
+import android.graphics.Rect;
import android.net.Uri;
+import android.os.IBinder;
import android.os.Message;
import android.tv.TvInputService.TvInputSessionImpl;
import android.util.Log;
import android.view.Surface;
import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
/**
* Implements the internal ITvInputSession interface to convert incoming calls on to it back to
@@ -38,6 +41,9 @@
private static final int DO_SET_SURFACE = 2;
private static final int DO_SET_VOLUME = 3;
private static final int DO_TUNE = 4;
+ private static final int DO_CREATE_OVERLAY_VIEW = 5;
+ private static final int DO_RELAYOUT_OVERLAY_VIEW = 6;
+ private static final int DO_REMOVE_OVERLAY_VIEW = 7;
private TvInputSessionImpl mTvInputSession;
private final HandlerCaller mCaller;
@@ -71,6 +77,20 @@
mTvInputSession.tune((Uri) msg.obj);
return;
}
+ case DO_CREATE_OVERLAY_VIEW: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ mTvInputSession.createOverlayView((IBinder) args.arg1, (Rect) args.arg2);
+ args.recycle();
+ return;
+ }
+ case DO_RELAYOUT_OVERLAY_VIEW: {
+ mTvInputSession.relayoutOverlayView((Rect) msg.obj);
+ return;
+ }
+ case DO_REMOVE_OVERLAY_VIEW: {
+ mTvInputSession.removeOverlayView(true);
+ return;
+ }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
return;
@@ -97,4 +117,20 @@
public void tune(Uri channelUri) {
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_TUNE, channelUri));
}
+
+ @Override
+ public void createOverlayView(IBinder windowToken, Rect frame) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_CREATE_OVERLAY_VIEW, windowToken,
+ frame));
+ }
+
+ @Override
+ public void relayoutOverlayView(Rect frame) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RELAYOUT_OVERLAY_VIEW, frame));
+ }
+
+ @Override
+ public void removeOverlayView() {
+ mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_OVERLAY_VIEW));
+ }
}
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index 4cf2b35..05f0b9c 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -17,6 +17,7 @@
package android.tv;
import android.content.ComponentName;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
@@ -24,6 +25,7 @@
import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;
+import android.view.View;
import java.util.ArrayList;
import java.util.HashMap;
@@ -320,8 +322,8 @@
/** The Session provides the per-session functionality of TV inputs. */
public static final class Session {
private final ITvInputManager mService;
- private final IBinder mToken;
private final int mUserId;
+ private IBinder mToken;
/** @hide */
private Session(ComponentName name, IBinder token, ITvInputManager service, int userId) {
@@ -332,10 +334,16 @@
/**
* Releases this session.
+ *
+ * @throws IllegalStateException if the session has been already released.
*/
public void release() {
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
try {
mService.releaseSession(mToken, mUserId);
+ mToken = null;
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -345,8 +353,12 @@
* Sets the {@link android.view.Surface} for this session.
*
* @param surface A {@link android.view.Surface} used to render video.
+ * @throws IllegalStateException if the session has been already released.
*/
- public void setSurface(Surface surface) {
+ void setSurface(Surface surface) {
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
// surface can be null.
try {
mService.setSurface(mToken, surface, mUserId);
@@ -360,8 +372,12 @@
*
* @param volume A volume value between 0.0f to 1.0f.
* @throws IllegalArgumentException if the volume value is out of range.
+ * @throws IllegalStateException if the session has been already released.
*/
public void setVolume(float volume) {
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
try {
if (volume < 0.0f || volume > 1.0f) {
throw new IllegalArgumentException("volume should be between 0.0f and 1.0f");
@@ -377,16 +393,90 @@
*
* @param channelUri The URI of a channel.
* @throws IllegalArgumentException if the argument is {@code null}.
+ * @throws IllegalStateException if the session has been already released.
*/
public void tune(Uri channelUri) {
if (channelUri == null) {
throw new IllegalArgumentException("channelUri cannot be null");
}
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
try {
mService.tune(mToken, channelUri, mUserId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
+
+ /**
+ * Creates an overlay view. Once the overlay view is created, {@link #relayoutOverlayView}
+ * should be called whenever the layout of its containing view is changed.
+ * {@link #removeOverlayView()} should be called to remove the overlay view.
+ * Since a session can have only one overlay view, this method should be called only once
+ * or it can be called again after calling {@link #removeOverlayView()}.
+ *
+ * @param view A view playing TV.
+ * @param frame A position of the overlay view.
+ * @throws IllegalArgumentException if any of the arguments is {@code null}.
+ * @throws IllegalStateException if {@code view} is not attached to a window or
+ * if the session has been already released.
+ */
+ void createOverlayView(View view, Rect frame) {
+ if (view == null) {
+ throw new IllegalArgumentException("view cannot be null");
+ }
+ if (frame == null) {
+ throw new IllegalArgumentException("frame cannot be null");
+ }
+ if (view.getWindowToken() == null) {
+ throw new IllegalStateException("view must be attached to a window");
+ }
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
+ try {
+ mService.createOverlayView(mToken, view.getWindowToken(), frame, mUserId);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Relayouts the current overlay view.
+ *
+ * @param frame A new position of the overlay view.
+ * @throws IllegalArgumentException if the arguments is {@code null}.
+ * @throws IllegalStateException if the session has been already released.
+ */
+ void relayoutOverlayView(Rect frame) {
+ if (frame == null) {
+ throw new IllegalArgumentException("frame cannot be null");
+ }
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
+ try {
+ mService.relayoutOverlayView(mToken, frame, mUserId);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Removes the current overlay view.
+ *
+ * @throws IllegalStateException if the session has been already released.
+ */
+ void removeOverlayView() {
+ if (mToken == null) {
+ throw new IllegalStateException("the session has been already released");
+ }
+ try {
+ mService.removeOverlayView(mToken, mUserId);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
}
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
index d7f6c32..80eb407 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/core/java/android/tv/TvInputService.java
@@ -18,7 +18,10 @@
import android.app.Service;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
@@ -26,7 +29,10 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
+import android.view.Gravity;
import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -125,7 +131,37 @@
/**
* Base class for derived classes to implement to provide {@link TvInputManager.Session}.
*/
- public abstract static class TvInputSessionImpl {
+ public abstract class TvInputSessionImpl {
+ private final WindowManager mWindowManager;
+ private WindowManager.LayoutParams mWindowParams;
+ private View mOverlayView;
+ private boolean mOverlayViewEnabled;
+ private IBinder mWindowToken;
+ private Rect mOverlayFrame;
+
+ public TvInputSessionImpl() {
+ mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ }
+
+ public void setOverlayViewEnabled(final boolean enable) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (enable == mOverlayViewEnabled) {
+ return;
+ }
+ mOverlayViewEnabled = enable;
+ if (enable) {
+ if (mWindowToken != null) {
+ createOverlayView(mWindowToken, mOverlayFrame);
+ }
+ } else {
+ removeOverlayView(false);
+ }
+ }
+ });
+ }
+
/**
* Called when the session is released.
*/
@@ -157,11 +193,22 @@
public abstract boolean onTune(Uri channelUri);
/**
+ * Called when an application requests to create an overlay view. Each session
+ * implementation can override this method and return its own view.
+ *
+ * @return a view attached to the overlay window
+ */
+ public View onCreateOverlayView() {
+ return null;
+ }
+
+ /**
* This method is called when the application would like to stop using the current input
* session.
*/
void release() {
onRelease();
+ removeOverlayView(true);
}
/**
@@ -186,6 +233,87 @@
onTune(channelUri);
// TODO: Handle failure.
}
+
+ /**
+ * Creates an overlay view. This calls {@link onCreateOverlayView} to get
+ * a view to attach to the overlay window.
+ *
+ * @param windowToken A window token of an application.
+ * @param frame A position of the overlay view.
+ */
+ void createOverlayView(IBinder windowToken, Rect frame) {
+ if (mOverlayView != null) {
+ mWindowManager.removeView(mOverlayView);
+ mOverlayView = null;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "create overlay view(" + frame + ")");
+ }
+ mWindowToken = windowToken;
+ mOverlayFrame = frame;
+ if (!mOverlayViewEnabled) {
+ return;
+ }
+ mOverlayView = onCreateOverlayView();
+ if (mOverlayView == null) {
+ return;
+ }
+ // TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
+ // an overlay window above the media window but below the application window.
+ int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+ // We make the overlay view non-focusable and non-touchable so that
+ // the application that owns the window token can decide whether to consume or
+ // dispatch the input events.
+ int flag = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ mWindowParams = new WindowManager.LayoutParams(
+ frame.right - frame.left, frame.bottom - frame.top,
+ frame.left, frame.top, type, flag, PixelFormat.TRANSPARENT);
+ mWindowParams.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ mWindowParams.gravity = Gravity.START | Gravity.TOP;
+ mWindowParams.token = windowToken;
+ mWindowManager.addView(mOverlayView, mWindowParams);
+ }
+
+ /**
+ * Relayouts the current overlay view.
+ *
+ * @param frame A new position of the overlay view.
+ */
+ void relayoutOverlayView(Rect frame) {
+ if (DEBUG) {
+ Log.d(TAG, "relayout overlay view(" + frame + ")");
+ }
+ mOverlayFrame = frame;
+ if (!mOverlayViewEnabled || mOverlayView == null) {
+ return;
+ }
+ mWindowParams.x = frame.left;
+ mWindowParams.y = frame.top;
+ mWindowParams.width = frame.right - frame.left;
+ mWindowParams.height = frame.bottom - frame.top;
+ mWindowManager.updateViewLayout(mOverlayView, mWindowParams);
+ }
+
+ /**
+ * Removes the current overlay view.
+ */
+ void removeOverlayView(boolean clearWindowToken) {
+ if (DEBUG) {
+ Log.d(TAG, "remove overlay view(" + mOverlayView + ")");
+ }
+ if (clearWindowToken) {
+ mWindowToken = null;
+ mOverlayFrame = null;
+ }
+ if (mOverlayView != null) {
+ mWindowManager.removeView(mOverlayView);
+ mOverlayView = null;
+ mWindowParams = null;
+ }
+ }
}
private final class ServiceHandler extends Handler {
diff --git a/core/java/android/tv/TvView.java b/core/java/android/tv/TvView.java
new file mode 100644
index 0000000..325950d
--- /dev/null
+++ b/core/java/android/tv/TvView.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2014 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.tv;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.tv.TvInputManager;
+import android.tv.TvInputManager.Session;
+import android.tv.TvInputManager.SessionCreateCallback;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewTreeObserver;
+
+/**
+ * View playing TV
+ */
+public class TvView extends SurfaceView {
+ private static final String TAG = "TvView";
+
+ private final Handler mHandler = new Handler();
+ private TvInputManager.Session mSession;
+ private Surface mSurface;
+ private boolean mOverlayViewCreated;
+ private Rect mOverlayViewFrame;
+ private boolean mGlobalListenersAdded;
+ private TvInputManager mTvInputManager;
+ private SessionCreateCallback mSessionCreateCallback;
+
+ private SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width
+ + ", height=" + height + ")");
+ if (holder.getSurface() == mSurface) {
+ return;
+ }
+ mSurface = holder.getSurface();
+ setSessionSurface(mSurface);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ mSurface = holder.getSurface();
+ setSessionSurface(mSurface);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ mSurface = null;
+ setSessionSurface(null);
+ }
+ };
+
+ public TvView(Context context) {
+ this(context, null, 0);
+ }
+
+ public TvView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TvView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ getHolder().addCallback(mSurfaceHolderCallback);
+ mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
+ }
+
+ /**
+ * Binds a TV input to this view. {@link SessionCreateCallback#onSessionCreated} will be
+ * called to send the result of this binding with {@link TvInputManager.Session}.
+ * If a TV input is already bound, the input will be unbound from this view and its session
+ * will be released.
+ *
+ * @param name TV input name will be bound to this view.
+ * @param callback called when TV input is bound. The callback sends
+ * {@link TvInputManager.Session}
+ * @throws IllegalArgumentException if any of the arguments is {@code null}.
+ */
+ public void bindTvInput(ComponentName name, SessionCreateCallback callback) {
+ if (name == null) {
+ throw new IllegalArgumentException("name cannot be null");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("callback cannot be null");
+ }
+ if (mSession != null) {
+ release();
+ }
+ // When bindTvInput is called multiple times before the callback is called,
+ // only the callback of the last bindTvInput call will be actually called back.
+ // The previous callbacks will be ignored. For the logic, mSessionCreateCallback
+ // is newly assigned for every bindTvInput call and compared with
+ // MySessionCreateCallback.this.
+ mSessionCreateCallback = new MySessionCreateCallback(callback);
+ mTvInputManager.createSession(name, mSessionCreateCallback, mHandler);
+ }
+
+ /**
+ * Unbinds a TV input currently bound. Its corresponding {@link TvInputManager.Session}
+ * is released.
+ */
+ public void unbindTvInput() {
+ if (mSession != null) {
+ release();
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ createSessionOverlayView();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ removeSessionOverlayView();
+ super.onDetachedFromWindow();
+ }
+
+ /** @hide */
+ @Override
+ protected void updateWindow(boolean force, boolean redrawNeeded) {
+ super.updateWindow(force, redrawNeeded);
+ relayoutSessionOverlayView();
+ }
+
+ private void release() {
+ setSessionSurface(null);
+ removeSessionOverlayView();
+ mSession.release();
+ mSession = null;
+ }
+
+ private void setSessionSurface(Surface surface) {
+ if (mSession == null) {
+ return;
+ }
+ mSession.setSurface(surface);
+ }
+
+ private void createSessionOverlayView() {
+ if (mSession == null || !isAttachedToWindow()
+ || mOverlayViewCreated) {
+ return;
+ }
+ mOverlayViewFrame = getViewFrameOnScreen();
+ mSession.createOverlayView(this, mOverlayViewFrame);
+ mOverlayViewCreated = true;
+ }
+
+ private void removeSessionOverlayView() {
+ if (mSession == null || !mOverlayViewCreated) {
+ return;
+ }
+ mSession.removeOverlayView();
+ mOverlayViewCreated = false;
+ mOverlayViewFrame = null;
+ }
+
+ private void relayoutSessionOverlayView() {
+ if (mSession == null || !isAttachedToWindow()
+ || !mOverlayViewCreated) {
+ return;
+ }
+ Rect viewFrame = getViewFrameOnScreen();
+ if (viewFrame.equals(mOverlayViewFrame)) {
+ return;
+ }
+ mSession.relayoutOverlayView(viewFrame);
+ mOverlayViewFrame = viewFrame;
+ }
+
+ private Rect getViewFrameOnScreen() {
+ int[] location = new int[2];
+ getLocationOnScreen(location);
+ return new Rect(location[0], location[1],
+ location[0] + getWidth(), location[1] + getHeight());
+ }
+
+ private class MySessionCreateCallback implements SessionCreateCallback {
+ final SessionCreateCallback mExternalCallback;
+
+ MySessionCreateCallback(SessionCreateCallback externalCallback) {
+ mExternalCallback = externalCallback;
+ }
+
+ @Override
+ public void onSessionCreated(Session session) {
+ if (this != mSessionCreateCallback) {
+ // This callback is obsolete.
+ session.release();
+ return;
+ }
+ mSession = session;
+ if (session != null) {
+ // mSurface may not be ready yet as soon as starting an application.
+ // In the case, we don't send Session.setSurface(null) unnecessarily.
+ // setSessionSurface will be called in surfaceCreated.
+ if (mSurface != null) {
+ setSessionSurface(mSurface);
+ }
+ createSessionOverlayView();
+ }
+ if (mExternalCallback != null) {
+ mExternalCallback.onSessionCreated(session);
+ }
+ }
+ }
+}
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 13cc88b..2cc91b9 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -130,7 +130,10 @@
private static final String IRI
= "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
- private static final String HOST_NAME = IRI + "(?:\\." + IRI + ")+";
+ private static final String GOOD_GTLD_CHAR =
+ "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+ private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
+ private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
public static final Pattern DOMAIN_NAME
= Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index a7ee12b..71296fa 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -161,6 +161,7 @@
} else if (tagName.equals(XML_MENU)) {
// A menu start tag denotes a submenu for an item
SubMenu subMenu = menuState.addSubMenuItem();
+ registerMenu(subMenu, attrs);
// Parse the submenu into returned SubMenu
parseMenu(parser, attrs, subMenu);
@@ -183,9 +184,9 @@
if (!menuState.hasAddedItem()) {
if (menuState.itemActionProvider != null &&
menuState.itemActionProvider.hasSubMenu()) {
- menuState.addSubMenuItem();
+ registerMenu(menuState.addSubMenuItem(), attrs);
} else {
- menuState.addItem();
+ registerMenu(menuState.addItem(), attrs);
}
}
} else if (tagName.equals(XML_MENU)) {
@@ -200,7 +201,30 @@
eventType = parser.next();
}
}
-
+
+ /**
+ * The method is a hook for layoutlib to do its magic.
+ * Nothing is needed outside of LayoutLib. However, it should not be deleted because it
+ * appears to do nothing.
+ */
+ private void registerMenu(@SuppressWarnings("unused") MenuItem item,
+ @SuppressWarnings("unused") AttributeSet set) {
+ }
+
+ /**
+ * The method is a hook for layoutlib to do its magic.
+ * Nothing is needed outside of LayoutLib. However, it should not be deleted because it
+ * appears to do nothing.
+ */
+ private void registerMenu(@SuppressWarnings("unused") SubMenu subMenu,
+ @SuppressWarnings("unused") AttributeSet set) {
+ }
+
+ // Needed by layoutlib.
+ /*package*/ Context getContext() {
+ return mContext;
+ }
+
private static class InflatedOnMenuItemClickListener
implements MenuItem.OnMenuItemClickListener {
private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
@@ -446,9 +470,11 @@
}
}
- public void addItem() {
+ public MenuItem addItem() {
itemAdded = true;
- setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle));
+ MenuItem item = menu.add(groupId, itemId, itemCategoryOrder, itemTitle);
+ setItem(item);
+ return item;
}
public SubMenu addSubMenuItem() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 23123dd..4a2cc1a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -422,7 +422,8 @@
mWindowType = type;
}
- private void updateWindow(boolean force, boolean redrawNeeded) {
+ /** @hide */
+ protected void updateWindow(boolean force, boolean redrawNeeded) {
if (!mHaveFrame) {
return;
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 60d7c78..924c331 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -178,11 +178,14 @@
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
- callbacks.onHardwarePostDraw(canvas);
- canvas.drawDisplayList(view.getDisplayList());
- callbacks.onHardwarePostDraw(canvas);
- mRootNode.end(canvas);
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ try {
+ callbacks.onHardwarePostDraw(canvas);
+ canvas.drawDisplayList(view.getDisplayList());
+ callbacks.onHardwarePostDraw(canvas);
+ } finally {
+ mRootNode.end(canvas);
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
view.mRecreateDisplayList = false;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1f9ba46..cb05b05 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4737,13 +4737,13 @@
private void manageFocusHotspot(boolean focused, View v) {
if (mBackground != null && mBackground.supportsHotspots()) {
final Rect r = new Rect();
- if (v != null) {
+ if (!focused && v != null) {
v.getBoundsOnScreen(r);
final int[] location = new int[2];
getLocationOnScreen(location);
r.offset(-location[0], -location[1]);
} else {
- r.set(mLeft, mTop, mRight, mBottom);
+ r.set(0, 0, mRight - mLeft, mBottom - mTop);
}
final float x = r.exactCenterX();
@@ -4858,16 +4858,13 @@
if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
mPrivateFlags &= ~PFLAG_FOCUSED;
- if (hasFocus()) {
- manageFocusHotspot(false, focused);
- }
-
if (propagate && mParent != null) {
mParent.clearChildFocus(this);
}
onFocusChanged(false, 0, null);
+ manageFocusHotspot(false, focused);
refreshDrawableState();
if (propagate && (!refocus || !rootViewRequestFocus())) {
@@ -14900,8 +14897,11 @@
final int width = bounds.width();
final int height = bounds.height();
final HardwareCanvas canvas = displayList.start(width, height);
- drawable.draw(canvas);
- displayList.end(canvas);
+ try {
+ drawable.draw(canvas);
+ } finally {
+ displayList.end(canvas);
+ }
// Set up drawable properties that are view-independent.
displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4e4f37b..23be203 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1514,43 +1514,46 @@
mResizeBuffer.prepare(mWidth, mHeight, false);
RenderNode layerRenderNode = mResizeBuffer.startRecording();
HardwareCanvas layerCanvas = layerRenderNode.start(mWidth, mHeight);
- final int restoreCount = layerCanvas.save();
+ try {
+ final int restoreCount = layerCanvas.save();
- int yoff;
- final boolean scrolling = mScroller != null
- && mScroller.computeScrollOffset();
- if (scrolling) {
- yoff = mScroller.getCurrY();
- mScroller.abortAnimation();
- } else {
- yoff = mScrollY;
+ int yoff;
+ final boolean scrolling = mScroller != null
+ && mScroller.computeScrollOffset();
+ if (scrolling) {
+ yoff = mScroller.getCurrY();
+ mScroller.abortAnimation();
+ } else {
+ yoff = mScrollY;
+ }
+
+ layerCanvas.translate(0, -yoff);
+ if (mTranslator != null) {
+ mTranslator.translateCanvas(layerCanvas);
+ }
+
+ RenderNode renderNode = mView.mRenderNode;
+ if (renderNode != null && renderNode.isValid()) {
+ layerCanvas.drawDisplayList(renderNode, null,
+ RenderNode.FLAG_CLIP_CHILDREN);
+ } else {
+ mView.draw(layerCanvas);
+ }
+
+ drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
+
+ mResizeBufferStartTime = SystemClock.uptimeMillis();
+ mResizeBufferDuration = mView.getResources().getInteger(
+ com.android.internal.R.integer.config_mediumAnimTime);
+
+ layerCanvas.restoreToCount(restoreCount);
+ layerRenderNode.end(layerCanvas);
+ layerRenderNode.setCaching(true);
+ layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
+ mTempRect.set(0, 0, mWidth, mHeight);
+ } finally {
+ mResizeBuffer.endRecording(mTempRect);
}
-
- layerCanvas.translate(0, -yoff);
- if (mTranslator != null) {
- mTranslator.translateCanvas(layerCanvas);
- }
-
- RenderNode renderNode = mView.mRenderNode;
- if (renderNode != null && renderNode.isValid()) {
- layerCanvas.drawDisplayList(renderNode, null,
- RenderNode.FLAG_CLIP_CHILDREN);
- } else {
- mView.draw(layerCanvas);
- }
-
- drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
-
- mResizeBufferStartTime = SystemClock.uptimeMillis();
- mResizeBufferDuration = mView.getResources().getInteger(
- com.android.internal.R.integer.config_mediumAnimTime);
-
- layerCanvas.restoreToCount(restoreCount);
- layerRenderNode.end(layerCanvas);
- layerRenderNode.setCaching(true);
- layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
- mTempRect.set(0, 0, mWidth, mHeight);
- mResizeBuffer.endRecording(mTempRect);
mAttachInfo.mHardwareRenderer.flushLayerUpdates();
}
mAttachInfo.mContentInsets.set(mPendingContentInsets);
@@ -2949,7 +2952,7 @@
}
}
}
-
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -3722,7 +3725,8 @@
if (result == InputMethodManager.DISPATCH_HANDLED) {
return FINISH_HANDLED;
} else if (result == InputMethodManager.DISPATCH_NOT_HANDLED) {
- return FINISH_NOT_HANDLED;
+ // The IME could not handle it, so skip along to the next InputStage
+ return FORWARD;
} else {
return DEFER; // callback will be invoked later
}
@@ -5820,6 +5824,13 @@
}
}
+ public void dispatchUnhandledInputEvent(InputEvent event) {
+ if (event instanceof KeyEvent) {
+ dispatchUnhandledKey((KeyEvent) event);
+ return;
+ }
+ }
+
public void dispatchAppVisibility(boolean visible) {
Message msg = mHandler.obtainMessage(MSG_DISPATCH_APP_VISIBILITY);
msg.arg1 = visible ? 1 : 0;
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 438a9da..225cd6d 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -29,6 +29,8 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.internal.R;
+
public abstract class AbsSeekBar extends ProgressBar {
private Drawable mThumb;
private int mThumbOffset;
@@ -289,28 +291,39 @@
*/
private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
int available = w - mPaddingLeft - mPaddingRight;
- int thumbWidth = thumb.getIntrinsicWidth();
- int thumbHeight = thumb.getIntrinsicHeight();
+ final int thumbWidth = thumb.getIntrinsicWidth();
+ final int thumbHeight = thumb.getIntrinsicHeight();
available -= thumbWidth;
// The extra space for the thumb to move on the track
available += mThumbOffset * 2;
- int thumbPos = (int) (scale * available + 0.5f);
+ final int thumbPos = (int) (scale * available + 0.5f);
- int topBound, bottomBound;
+ final int top, bottom;
if (gap == Integer.MIN_VALUE) {
- Rect oldBounds = thumb.getBounds();
- topBound = oldBounds.top;
- bottomBound = oldBounds.bottom;
+ final Rect oldBounds = thumb.getBounds();
+ top = oldBounds.top;
+ bottom = oldBounds.bottom;
} else {
- topBound = gap;
- bottomBound = gap + thumbHeight;
+ top = gap;
+ bottom = gap + thumbHeight;
}
-
- // Canvas will be translated, so 0,0 is where we start drawing
+
final int left = (isLayoutRtl() && mMirrorForRtl) ? available - thumbPos : thumbPos;
- thumb.setBounds(left, topBound, left + thumbWidth, bottomBound);
+ final int right = left + thumbWidth;
+
+ final Drawable background = getBackground();
+ if (background != null && background.supportsHotspots()) {
+ final Rect bounds = mThumb.getBounds();
+ final int offsetX = mPaddingLeft - mThumbOffset;
+ final int offsetY = mPaddingTop;
+ background.setHotspotBounds(left + offsetX, bounds.top + offsetY,
+ right + offsetX, bounds.bottom + offsetY);
+ }
+
+ // Canvas will be translated, so 0,0 is where we start drawing
+ thumb.setBounds(left, top, right, bottom);
}
/**
@@ -328,6 +341,7 @@
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
+
if (mThumb != null) {
canvas.save();
// Translate the padding. For the x, we need to allow the thumb to
@@ -424,10 +438,24 @@
return true;
}
+ private void setHotspot(int id, float x, float y) {
+ final Drawable bg = getBackground();
+ if (bg != null && bg.supportsHotspots()) {
+ bg.setHotspot(id, x, y);
+ }
+ }
+
+ private void clearHotspot(int id) {
+ final Drawable bg = getBackground();
+ if (bg != null && bg.supportsHotspots()) {
+ bg.removeHotspot(id);
+ }
+ }
+
private void trackTouchEvent(MotionEvent event) {
final int width = getWidth();
final int available = width - mPaddingLeft - mPaddingRight;
- int x = (int)event.getX();
+ final int x = (int) event.getX();
float scale;
float progress = 0;
if (isLayoutRtl() && mMirrorForRtl) {
@@ -451,7 +479,8 @@
}
final int max = getMax();
progress += scale * max;
-
+
+ setHotspot(R.attr.state_pressed, x, (int) event.getY());
setProgress((int) progress, true);
}
@@ -477,6 +506,7 @@
* canceled.
*/
void onStopTrackingTouch() {
+ clearHotspot(R.attr.state_pressed);
mIsDragging = false;
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 4298545..9e17cca 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -261,15 +261,13 @@
@Override
protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
final Drawable buttonDrawable = mButtonDrawable;
if (buttonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
final int drawableHeight = buttonDrawable.getIntrinsicHeight();
final int drawableWidth = buttonDrawable.getIntrinsicWidth();
- int top = 0;
+ final int top;
switch (verticalGravity) {
case Gravity.BOTTOM:
top = getHeight() - drawableHeight;
@@ -277,12 +275,24 @@
case Gravity.CENTER_VERTICAL:
top = (getHeight() - drawableHeight) / 2;
break;
+ default:
+ top = 0;
}
- int bottom = top + drawableHeight;
- int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
- int right = isLayoutRtl() ? getWidth() : drawableWidth;
+ final int bottom = top + drawableHeight;
+ final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
+ final int right = isLayoutRtl() ? getWidth() : drawableWidth;
buttonDrawable.setBounds(left, top, right, bottom);
+
+ final Drawable background = getBackground();
+ if (background != null && background.supportsHotspots()) {
+ background.setHotspotBounds(left, top, right, bottom);
+ }
+ }
+
+ super.onDraw(canvas);
+
+ if (buttonDrawable != null) {
buttonDrawable.draw(canvas);
}
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 3d23e4d..08af4de 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -773,8 +773,6 @@
@Override
protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
final Rect tempRect = mTempRect;
final Drawable trackDrawable = mTrackDrawable;
final Drawable thumbDrawable = mThumbDrawable;
@@ -785,16 +783,12 @@
final int switchRight = mSwitchRight;
final int switchBottom = mSwitchBottom;
trackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
- trackDrawable.draw(canvas);
-
- final int saveCount = canvas.save();
-
trackDrawable.getPadding(tempRect);
+
final int switchInnerLeft = switchLeft + tempRect.left;
final int switchInnerTop = switchTop + tempRect.top;
final int switchInnerRight = switchRight - tempRect.right;
final int switchInnerBottom = switchBottom - tempRect.bottom;
- canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
// Relies on mTempRect, MUST be called first!
final int thumbPos = getThumbOffset();
@@ -803,6 +797,18 @@
int thumbLeft = switchInnerLeft - tempRect.left + thumbPos;
int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + tempRect.right;
thumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
+
+ final Drawable background = getBackground();
+ if (background != null && background.supportsHotspots()) {
+ background.setHotspotBounds(thumbLeft, switchTop, thumbRight, switchBottom);
+ }
+
+ super.onDraw(canvas);
+
+ trackDrawable.draw(canvas);
+
+ final int saveCount = canvas.save();
+ canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
thumbDrawable.draw(canvas);
final int drawableState[] = getDrawableState();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4c11fa9..eaedba5 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5580,13 +5580,13 @@
if (end) {
Slog.w(TAG, "New history ends before old history!");
} else if (!out.same(mHistoryReadTmp)) {
- long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
pw.println("Histories differ!");
pw.println("Old history:");
- (new HistoryPrinter()).printNextItem(pw, out, now, false, true);
+ (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
pw.println("New history:");
- (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now, false, true);
+ (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
+ true);
pw.flush();
}
}
@@ -5664,7 +5664,12 @@
return false;
}
+ final long lastRealtime = out.time;
+ final long lastWalltime = out.currentTime;
readHistoryDelta(mHistoryBuffer, out);
+ if (out.cmd != HistoryItem.CMD_CURRENT_TIME && lastWalltime != 0) {
+ out.currentTime = lastWalltime + (out.time - lastRealtime);
+ }
return true;
}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index b776226..5d7d322 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -392,8 +392,8 @@
private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
final int ordering = getOrdering(categoryOrder);
- final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
- ordering, title, mDefaultShowAsAction);
+ final MenuItemImpl item = createNewMenuItem(group, id, categoryOrder, ordering, title,
+ mDefaultShowAsAction);
if (mCurrentMenuInfo != null) {
// Pass along the current menu info
@@ -405,7 +405,14 @@
return item;
}
-
+
+ // Layoutlib overrides this method to return its custom implementation of MenuItemImpl
+ private MenuItemImpl createNewMenuItem(int group, int id, int categoryOrder, int ordering,
+ CharSequence title, int defaultShowAsAction) {
+ return new MenuItemImpl(this, group, id, categoryOrder, ordering, title,
+ defaultShowAsAction);
+ }
+
public MenuItem add(CharSequence title) {
return addInternal(0, 0, 0, title);
}
diff --git a/core/res/res/color/primary_text_quantum_dark.xml b/core/res/res/color/primary_text_quantum_dark.xml
new file mode 100644
index 0000000..1fcd0e3
--- /dev/null
+++ b/core/res/res/color/primary_text_quantum_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_quantum_dark"/>
+ <item android:color="@color/primary_text_default_quantum_dark"/>
+</selector>
diff --git a/core/res/res/color/primary_text_quantum_light.xml b/core/res/res/color/primary_text_quantum_light.xml
new file mode 100644
index 0000000..1ec1634
--- /dev/null
+++ b/core/res/res/color/primary_text_quantum_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_quantum_light"/>
+ <item android:color="@color/primary_text_default_quantum_light"/>
+</selector>
diff --git a/core/res/res/drawable-hdpi/ic_settings.png b/core/res/res/drawable-hdpi/ic_settings.png
new file mode 100644
index 0000000..cfa539f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_settings.png b/core/res/res/drawable-mdpi/ic_settings.png
new file mode 100644
index 0000000..e6237eb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_settings.png b/core/res/res/drawable-xhdpi/ic_settings.png
new file mode 100644
index 0000000..208089d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_settings.png b/core/res/res/drawable-xxhdpi/ic_settings.png
new file mode 100644
index 0000000..452942e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable/btn_color_quantum.xml b/core/res/res/drawable/btn_color_quantum.xml
index e923003..2da9226 100644
--- a/core/res/res/drawable/btn_color_quantum.xml
+++ b/core/res/res/drawable/btn_color_quantum.xml
@@ -19,7 +19,8 @@
<selector>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="?attr/colorButtonNormal" />
+ android:tint="?attr/colorButtonNormal"
+ android:alpha="?attr/disabledAlpha" />
</item>
<item>
<nine-patch android:src="@drawable/btn_qntm_alpha"
diff --git a/core/res/res/drawable/btn_default_quantum.xml b/core/res/res/drawable/btn_default_quantum.xml
index 2919621..c6a3a33 100644
--- a/core/res/res/drawable/btn_default_quantum.xml
+++ b/core/res/res/drawable/btn_default_quantum.xml
@@ -17,7 +17,18 @@
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorButtonPressed">
<item>
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="?attr/colorButtonNormal" />
+ <selector>
+ <item android:state_enabled="false">
+ <nine-patch
+ android:src="@drawable/btn_qntm_alpha"
+ android:tint="?attr/colorButtonNormal"
+ android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item>
+ <nine-patch
+ android:src="@drawable/btn_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
+ </item>
+ </selector>
</item>
</touch-feedback>
diff --git a/core/res/res/drawable/btn_radio_quantum.xml b/core/res/res/drawable/btn_radio_quantum.xml
index 152e3d3..0f9ebce 100644
--- a/core/res/res/drawable/btn_radio_quantum.xml
+++ b/core/res/res/drawable/btn_radio_quantum.xml
@@ -15,18 +15,20 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:state_enabled="false" android:state_checked="true">
+ <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_checked="true">
<bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
android:tint="?attr/colorControlActivated" />
</item>
- <item android:state_enabled="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
<item>
<bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/edit_text_quantum.xml b/core/res/res/drawable/edit_text_quantum.xml
index d1f9831..c42c7b7 100644
--- a/core/res/res/drawable/edit_text_quantum.xml
+++ b/core/res/res/drawable/edit_text_quantum.xml
@@ -14,29 +14,26 @@
limitations under the License.
-->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="true">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
- <item android:state_window_focused="false" android:state_enabled="false">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
- <item android:state_enabled="true" android:state_focused="true">
- <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_enabled="true" android:state_activated="true">
- <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_enabled="true">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
+<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
+ android:tint="?attr/colorControlActivated">
<item>
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ <selector>
+ <item android:state_window_focused="false">
+ <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_enabled="false">
+ <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_focused="false" android:state_activated="false">
+ <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item>
+ <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ </selector>
</item>
-</selector>
+</touch-feedback>
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum.xml b/core/res/res/drawable/scrubber_control_selector_quantum.xml
index e34f64a..ef3af0c 100644
--- a/core/res/res/drawable/scrubber_control_selector_quantum.xml
+++ b/core/res/res/drawable/scrubber_control_selector_quantum.xml
@@ -19,10 +19,6 @@
<bitmap android:src="@drawable/scrubber_control_off_qntm_alpha"
android:tint="?attr/colorControlNormal" />
</item>
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
<item>
<bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/switch_inner_quantum.xml b/core/res/res/drawable/switch_inner_quantum.xml
index 915377e..856895e 100644
--- a/core/res/res/drawable/switch_inner_quantum.xml
+++ b/core/res/res/drawable/switch_inner_quantum.xml
@@ -15,18 +15,20 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_pressed="true">
+ <item android:state_enabled="false" android:state_checked="true">
<nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_enabled="false">
+ <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_on_qntm_alpha"
android:tint="?attr/colorControlActivated" />
</item>
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
<item>
<nine-patch android:src="@drawable/switch_off_qntm_alpha"
android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index bf8037a..2988f06 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkroniseer"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Te veel <xliff:g id="CONTENT_TYPE">%s</xliff:g> uitgevee."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet se berging is vol. Vee \'n aantal lêers uit om spasie vry te maak."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Horlosieberging is vol! Vee \'n paar lêers uit om plek te maak."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Foon se berging is vol. Vee \'n aantal lêers uit om spasie vry te maak."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netwerk kan dalk gemonitor word"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Deur \'n onbekende derde party"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Luitoestel aan"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Sit tans af…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Jou tablet gaan nou afskakel."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Jou horlosie gaan nou afskakel."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Jou foon gaan nou afsit."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Wil jy afskakel?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Herlaai na veilige modus"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Laat die program toe om \'n kennisgewing uit te saai dat \'n SMS-boodskap ontvang is. Kwaadwillige programme kan dit dalk gebruik om inkomende SMS-boodskappe na te maak."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"stuur WAP-PUSH-ontvange uitsending"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Laat die program toe om \'n kennisgewing uit te saai dat \'n WAP PUSH-boodskap ontvang is. Kwaadwillige programme kan dit dalk gebruik om MMS-boodskap-ontvangsbewyse na te maak of die inhoud van enige webbladsy stilweg te vervang met kwaadwillige variante."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"stuur uitsending vir netwerktelling"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Laat die program toe om \'n kennisgewing uit te saai dat netwerke tellings moet kry. Nooit vir normale programme nodig nie."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"beperk hoeveelheid lopende prosesse"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Laat die program toe om die maksimum getal prosesse te beheer wat sal loop. Nooit nodig vir normale programme nie."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"dwing agtergrondprogramme om te sluit"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Dit laat die houer toe om aan die top-koppelvlak van \'n afstandskerm te koppel. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind aan \'n legstukdiens"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind aan \'n roeteverskafferdiens"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Laat die houer toe om aan enige geregistreerde roeteverskaffers te bind. Behoort nooit vir normale programme nodig te wees nie."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Dit moet nooit vir normale programme nodig wees nie."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bind aan \'n TV-invoer"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Verander WiMAX-status"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Laat die program toe om die tablet aan WiMAX-netwerke te koppel en daarvan te ontkoppel."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Laat die program toe om die foon aan WiMAX-netwerke te koppel en daarvan te ontkoppel."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"gee telling vir netwerke"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Laat die program toe om netwerke te gradeer en beïnvloed watter netwerke die tablet moet verkies."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Laat die program toe om netwerke te gradeer en beïnvloed watter netwerke die foon moet verkies."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"bind saam met Bluetooth-toestelle"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Laat die program toe om die opstelling van Bluetooth op die tablet te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Laat die program toe om die opstelling van die Bluetooth op die foon te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 585857b..a32c834 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ሥምሪያ"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"በጣም ብዙ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ስርዞች።"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"የጡባዊ ተኮ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"የእጅ ሰዓት ማከማቻ ሙሉ ነው። ቦታ ለማስለቀቅ አንዳንድ ፋይሎችን ይሰርዙ።"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"የስልክ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"አውታረ መረብ በክትትል ውስጥ ሊሆን ይችላል"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ባልታወቀ ሶስተኛ ወገን"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"መጥሪያ በርቷል"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"በመዝጋት ላይ..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ጡባዊዎ ይዘጋል።"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"የእርስዎ የእጅ ሰዓት ይዘጋል።"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"ስልክዎ ይዘጋል።"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"ዘግተህ መውጣት ትፈልጋለህ?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"በአስተማማኝ ኹነታ ውስጥ ዳግም አስጀምር"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ኤስ ኤም ኤስ መልዕክት መቀበሉን ማሳወቂያ እንዲያሰራጭ ለመተግበሪያው ይፈቅዳሉ፡፡ መጪ ኤስ ኤም ኤስ መልዕክቶችን አመሳስሎ በማቅረብ ተንኮል አዘል መተግበሪያዎች ይሄንን ሊጠቀሙበት ይችላሉ፡፡"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"የWAP-PUSH ደርስዋል ስርጭት ላክ"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"የWAP PUSH መልዕክት እንደተቀበለ ማሳወቂያ ለማሰራጨት ለመተግበሪያው ይፈቅዳሉ፡፡ ኤም ኤም ኤስ መልዕክት መቀበልን ለማስመሰል ወይም በተንኮል አዘል መሰሎች ለማንኛውም የድር ገፅ ይዘት በዝምታ ለመተካት ተንኮል አዘል መተግበሪያዎች ሊጠቀሙበት ይችላሉ፡፡"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ለአውታረ መረቦች የነጥብ ስጥ ስርጭት ይልካል"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"መተግበሪያው አውታረ መረቦች ነጥብ እንዲያዝለት የሚፈልጉት አንድ ማሳወቂያ እንዲያሰራጭ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"የአሂድ ሂደቶችን ቁጥር ወስን"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"የሚሄዱ ሂደቶችን የመጨረሻ ቁጥር ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም አያስፈልግም፡፡"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"የጀርባ መተግበሪያዎች እንዲዘጉ አስገድዳቸው"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ያዢው ከአንድ የርቀት ማሳያ ከፍተኛ-ደረጃ በይነገጽ ጋር እንዲጠርዝ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ወደ ፍርግም አገልግሎት አያይዝ"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ፍርግም አገልግሎት ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ከመንገድ አቅራቢዎች አገልግሎት ጋር ያስተሳስሩ"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"አቃፊው ከማናቸውም የተመዘገቡ የመንገድ አቅራቢዎች ጋር እንዲተሳሰር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ከመሣሪያ አስተዳደር ጋር ተገናኝ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ያዡ በይነመረብን ለመሣሪያ አስተዳዳሪ ለመላክ ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች በፍፁም አያስፈልግም።"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ከአንድ የቴሌቪዥን ግብዓት ጋር እሰር"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"የWiMAX ሁኔታ ለውጥ"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"መተግበሪያው ጡባዊ ተኮውን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"መተግበሪያው ስልኩን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ለአውታረ መረቦች ነጥብ ይሰጣል"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"መተግበሪያው ለአውታረ መረቦች ደረጃ እንዲሰጥ እና ጡባዊው የትኛዎቹን አውታረ መረቦች እንደሚመርጥ ላይ ተጽዕኖ እንዲያሳርፍ ያስችለዋል።"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"መተግበሪያው ለአውታረ መረቦች ደረጃ እንዲሰጥ እና ስልኩ የትኛዎቹን አውታረ መረቦች እንደሚመርጥ ላይ ተጽዕኖ እንዲያሳርፍ ያስችለዋል።"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"ከብሉቱዝ መሣሪያዎች ጋር ተጣመር"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"መተግበሪያው በጡባዊ ተኮው ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"መተግበሪያው በስልኩ ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 468c14b..86d2be3 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"للسماح للتطبيق ببث إشعار باستلام رسالة قصيرة SMS. قد تستخدم التطبيقات الضارة هذا لتزييف الرسائل القصيرة SMS الواردة."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"إرسال بث WAP-PUSH المستلم"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"للسماح للتطبيق ببث إشعار باستلام رسالة WAP PUSH. يمكن أن تستخدم التطبيقات الضارة هذا لتزيف استلام رسالة وسائط متعددة أو لاستبدال محتوى أي صفحة ويب بمتغيرات ضارة بشكل غير ملحوظ."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"إرسال بث الشبكات التي تم تقييمها"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"السماح للتطبيق لكي يبث إشعارًا يفيد بأنه يلزم تقييم الشبكات. لا يلزم ذلك مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"تحديد عدد العمليات قيد التشغيل"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"للسماح للتطبيق بالتحكم في الحد الأقصى لعدد العمليات التي سيتم تشغيلها. غير مطلوب على الإطلاق للتطبيقات العادية."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"فرض إغلاق تطبيقات الخلفية"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للعرض عن بُعد. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"الربط مع خدمة مزود طريق"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"للسماح لحامل البطاقة الربط مع أي مزود طريق مسجل. لا يجب استخدامه على الإطلاق مع التطبيقات العادية."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"الالتزام بإدخال التلفزيون"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغيير حالة WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"للسماح للتطبيق بتوصيل الجهاز اللوحي بشبكات WiMAX وقطع اتصاله بها."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"للسماح للتطبيق بتوصيل الهاتف بشبكات WiMAX وقطع اتصاله بها."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"تقييم الشبكات"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"للسماح للتطبيق بترتيب الشبكات وتحديد تلك الشبكات التي من المفضل أن يستخدمها الجهاز اللوحي."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"للسماح للتطبيق بترتيب الشبكات وتحديد تلك الشبكات التي من المفضل أن يستخدمها الهاتف."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"الاتصال بأجهزة بلوتوث"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"للسماح للتطبيق بعرض تهيئة البلوتوث على الجهاز اللوحي وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"للسماح للتطبيق بعرض تهيئة البلوتوث على الهاتف وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index bb2bf43..fcf3e1b 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхронизиране"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Изтриванията за <xliff:g id="CONTENT_TYPE">%s</xliff:g> са твърде много."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Хранилището на таблета е пълно. Изтрийте файлове, за да освободите място."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Хранилището на часовника е пълно. Изтрийте файлове, за да освободите място."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Хранилището на телефона е пълно. Изтрийте файлове, за да освободите място."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежата може да се наблюдава"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"От неизвестна трета страна"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Звъненето е включено"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Изключва се..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблетът ви ще се изключи."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Часовникът ви ще се изключи."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефонът ви ще се изключи."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Искате ли да изключите?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Рестартиране в безопасен режим"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Разрешава на приложението да излъчва известие, че е получен SMS. Злонамерените приложения могат да използват това, за да фалшифицират входящите SMS съобщения."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"изпращане на излъчване при получено WAP PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Разрешава на приложението да излъчва известие, че е получено WAP PUSH съобщение. Злонамерените приложения могат да използват това, за да фалшифицират получаването на MMS или скрито да заменят съдържанието на произволна уеб страница със злонамерен вариант."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"изпращане на излъчване за оценяване на мрежите"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Разрешава на приложението да излъчи известие, че мрежите трябва да бъдат оценени. Не е необходимо за нормалните приложения."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ограничаване на броя изпълнявани процеси"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Разрешава на приложението да контролира максималния брой изпълнявани процеси. Нормалните приложения никога не се нуждаят от това."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудително затваряне на приложенията на заден план"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Разрешава на притежателя да се свърже с интерфейса от първо ниво на отдалечен екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за приспособления. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"свързване с услуга за предоставяне на маршрути"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Разрешава на собственика да се свързва с всички регистрирани доставчици на маршрути. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаимодействие с администратор на устройството"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Разрешава на притежателя да изпраща намерения до администратор на устройството. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"свързване към вход на телевизор"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промяна на състоянието на WiMAX мрежата"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Разрешава на приложението да свързва таблета към WiMAX мрежа и да прекратява връзката му с нея."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Разрешава на приложението да свързва телефона към WiMAX мрежа и да прекратява връзката му с нея."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"оценяване на мрежите"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Разрешава на приложението да класира мрежите и да повлияе върху това, кои да са предпочитаните за таблета."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Разрешава на приложението да класира мрежите и да повлияе върху това, кои да са предпочитаните за телефона."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"сдвояване с устройства с Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Разрешава на приложението да вижда конфигурацията на Bluetooth на таблета и да изгражда и приема връзки със сдвоени устройства."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Разрешава на приложението да вижда конфигурацията на Bluetooth на телефона и да изгражда и приема връзки със сдвоени устройства."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 11601bb..b422a6d 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronització"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Massa supressions de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"L\'emmagatzematge de la tauleta és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"L\'emmagatzematge del rellotge està ple. Suprimeix uns quants fitxers per alliberar espai."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"L\'emmagatzematge del telèfon és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"És possible que la xarxa estigui supervisada"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Per un tercer desconegut"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Timbre activat"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"S\'està apagant..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"La tauleta s\'apagarà."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"El rellotge s\'apagarà."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"El telèfon s\'apagarà."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Vols apagar-lo?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reinicia en mode segur"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet que l\'aplicació difongui una notificació en què s\'indiqui que s\'ha rebut un missatge SMS. Les aplicacions malicioses poden fer servir aquesta funció per falsificar els missatges SMS entrants."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar una difusió de tipus WAP-PUSH-received"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet que l\'aplicació difongui una notificació que indica que s\'ha rebut un missatge d\'inserció WAP. Les aplicacions malicioses poden utilitzar-ho per falsificar la recepció dels missatges MMS o per substituir silenciosament el contingut d\'una pàgina web per variants malicioses."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar l\'emissió de la puntuació de les xarxes"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permet que l\'aplicació emeti una notificació necessària perquè les xarxes rebin una puntuació. No es necessita mai per a les aplicacions normals."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar el nombre de processos en execució"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet que l\'aplicació controli el nombre màxim de processos que s\'executaran. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"com fer que es tanquin les aplicacions en segon pla"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet que el titular es vinculi a la interfície de nivell superior d\'una pantalla remota. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"establir vincles amb un servei d\'aprovisionament de rutes"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permet que el titular estableixi vincles amb els proveïdors de rutes registrats. No hauria de ser mai necessari per a les aplicacions normals."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet que el titular enviï intents a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"Vinculació a una entrada de televisor"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Canvia l\'estat de WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet que l\'aplicació connecti i desconnecti la tauleta de les xarxes WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet que l\'aplicació connecti i desconnecti el telèfon de les xarxes WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar les xarxes"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permet que l\'aplicació classifiqui les xarxes i indiqui quines han de ser les xarxes preferides de la tauleta."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permet que l\'aplicació classifiqui les xarxes i indiqui quines han de ser les xarxes preferides del telèfon."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"emparella amb dispositius Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet que l\'aplicació visualitzi la configuració de Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet que una aplicació visualitzi la configuració de Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ef6c7e9..416eca9 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Umožňuje aplikaci vysílat oznámení o přijetí zprávy SMS. Škodlivé aplikace mohou toto oprávnění použít k vytváření falešných příchozích zpráv SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"odeslání vysílání typu WAP-PUSH-received"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Umožňuje aplikaci vysílat oznámení o přijetí zprávy WAP PUSH. Škodlivé aplikace mohou toto oprávnění použít k vytváření falešných přijatých zpráv MMS nebo utajenému nahrazení obsahu libovolné webové stránky jejich škodlivými variantami."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"odeslání skóre vysílaných sítěmi"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Umožňuje aplikaci vysílat oznámení, že je třeba zadat skóre sítí. Běžné aplikace toto oprávnění nepotřebují."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"omezení počtu spuštěných procesů"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikaci řídit maximální počet spuštěných procesů. Běžné aplikace toto oprávnění nikdy nepotřebují."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynucení zavření aplikací na pozadí"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteli připojit se k vysokoúrovňovému rozhraní vzdáleného displeje. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteli navázat se na nejvyšší úroveň služby widgetu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"navázání na službu poskytovatele tras"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umožňuje držiteli navázat se na libovolného poskytovatele registrovaných tras. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovat se správcem zařízení"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteli oprávnění odesílat informace správci zařízení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"navázání na televizní vstup"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Změnit stav připojení WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikaci připojovat tablet k sítím WiMAX a odpojovat jej od nich."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Umožňuje aplikaci připojovat telefon k sítím WiMAX a odpojovat jej od nich."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"zadání skóre sítí"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Umožňuje aplikaci hodnotit sítě a ovlivňovat, které sítě by měl tablet preferovat."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Umožňuje aplikaci hodnotit sítě a ovlivňovat, které sítě by měl telefon preferovat."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"párování se zařízeními Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikaci zobrazit konfiguraci tabletu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikaci zobrazit konfiguraci telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index be6e28e..7e08df5 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkroniser"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"For mange <xliff:g id="CONTENT_TYPE">%s</xliff:g> sletninger"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Din tablets lager er fuldt. Slet nogle filer for at frigøre plads."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Urets lager er fuldt. Slet nogle filer for at frigøre plads."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefonens lager er fuldt. Slet nogle filer for at frigøre plads."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netværket kan være overvåget"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Af en ukendt tredjepart"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ringeren er aktiveret"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Lukker ned..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din tablet slukkes nu."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Dit ur lukkes ned."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon slukkes nu."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Vil du slukke?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Genstart i sikker tilstand"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Tillader, at appen kan udsende en underretning om, at der er modtaget en sms-besked. Ondsindede apps kan bruge dette til at simulere indgående sms-beskeder."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-modtaget udsendelse"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Tillader, at appen kan udsende en underretning om, at der er modtaget en WAP PUSH-besked. Ondsindede apps kan bruge dette til at simulere modtagelse af mms-beskeder eller i det skjulte erstatte indholdet på en webside med ondsindede varianter."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"sende underretninger om bedømmelse af netværk"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Tillader, at appen kan udsende en underretning om, at netværket skal bedømmes. Dette er aldrig nødvendigt for almindelige apps."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"begræns antallet af kørende processer"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillader, at appen kan kontrollere det maksimale antal kørende processer. Dette er aldrig nødvendigt til normale apps."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge baggrundsapps til at lukke"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Tillader, at brugeren kan foretage en binding til grænsefladens øverste niveau på en ekstern skærm. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"oprette tilknytning til en ruteudbydertjeneste"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Tillader, at indehaveren opretter tilknytninger til registrerede ruteudbydere. Dette bør aldrig være nødvendigt for normale apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillader, at brugeren kan sende hensigter til en enhedsadministrator. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"knyt til en tv-indgang"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Skift WiMAX-tilstand"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillader, at appen kan oprette forbindelse fra tabletten og afbryde forbindelsen til tabletten på WiMAX-netværk."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Tillader, at appen kan oprette forbindelse fra telefonen og afbryde forbindelsen til telefonen på WiMAX-netværk."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"bedømme netværk"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Tillader, at appen rangerer netværk og påvirker, hvilke netværk tabletten bør foretrække."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Tillader, at appen rangerer netværk og påvirker, hvilke netværk telefonen bør foretrække."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"parre med Bluetooth-enheder"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillader, at appen kan læse konfigurationen af Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillader, at appen kan læse konfigurationen af Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 3ba4c6f..162d0d8 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisierung"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Der Tablet-Speicher ist voll. Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Der Speicher Ihrer Uhr ist voll. Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Der Handyspeicher ist voll! Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Das Netzwerk wird möglicherweise überwacht."</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Von einem unbekannten Dritten"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Klingelton ein"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Wird heruntergefahren..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ihr Tablet wird heruntergefahren."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ihre Uhr wird heruntergefahren."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon wird heruntergefahren."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Möchten Sie das Gerät herunterfahren?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Im abgesicherten Modus starten"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine SMS empfangen wurde. Schädliche Apps können so eingehende SMS fälschen."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Von WAP-PUSH empfangenen Broadcast senden"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine WAP PUSH-Nachricht empfangen wurde. Schädliche Apps können so den Empfang von MMS vortäuschen oder unbemerkt den Inhalt einer beliebigen Webseite durch schädliche Inhalte ersetzen."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"Netzwerkbewertungen senden"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ermöglicht der App, Benachrichtigungen zu senden, dass Netzwerke bewertet werden müssen. Für normale Apps sollte dies nie erforderlich sein."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"Anzahl der laufenden Prozesse beschränken"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ermöglicht der App, die maximale Anzahl an aktiven Prozessen zu steuern. Wird nie für normale Apps benötigt."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Apps im Hintergrund schließen"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ermöglicht dem Halter, sich an die Oberfläche eines Remote-Displays auf oberster Ebene zu binden. Sollte für normale Apps nie benötigt werden."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ermöglicht dem Halter, sich an die Oberfläche eines Widget-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"An Routenanbieterdienst binden"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ermöglicht dem Inhaber die Bindung an registrierte Routenanbieter. Sollte für normale Apps nicht erforderlich sein"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Interaktion mit einem Geräteadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ermöglicht dem Halter, Intents an einen Geräteadministrator zu senden. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"An eine TV-Eingabe binden"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-Status ändern"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ermöglicht der App, eine Verbindung zwischen dem Tablet und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ermöglicht der App, eine Verbindung zwischen dem Telefon und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"Netzwerke bewerten"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ermöglicht der App, Netzwerke zu bewerten und die Auswahl des jeweiligen Netzwerks für das Tablet zu beeinflussen"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ermöglicht der App, Netzwerke zu bewerten und die Auswahl des jeweiligen Netzwerks für das Telefon zu beeinflussen"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Pairing mit Bluetooth-Geräten durchführen"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ermöglicht der App, die Bluetooth-Konfiguration eines Tablets einzusehen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b951897..6f013b2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Συγχρονισμός"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Ο αποθηκευτικός χώρος του tablet είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Από ένα άγνωστο τρίτο μέρος"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ειδοποίηση ήχου ενεργή"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Απενεργοποίηση..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Το tablet σας θα απενεργοποιηθεί."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Η παρακολούθησή σας θα τερματιστεί."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Το τηλέφωνό σας θα απενεργοποιηθεί."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Θέλετε να γίνει τερματισμός λειτουργίας;"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Επανεκκίνηση στην ασφαλή λειτουργία"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Επιτρέπει στην εφαρμογή την εκπομπή ειδοποίησης σχετικά με τη λήψη μηνύματος SMS. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για τη δημιουργία πλαστών εισερχόμενων μηνυμάτων SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"αποστολή εκπομπής που έχει ληφθεί με WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Επιτρέπει στην εφαρμογή τη μετάδοση μιας ειδοποίησης ότι έχει ληφθεί κάποιο μήνυμα WAP PUSH. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για τη λήψη πλαστών μηνυμάτων MMS ή την εν αγνοία του χρήστη αντικατάσταση του περιεχομένου οποιασδήποτε ιστοσελίδας με κακόβουλες παραλλαγές."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"αποστολή μετάδοσης κατάταξης δικτύων"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Επιτρέπει στην εφαρμογή να μεταδίδει μια ειδοποίηση ότι απαιτείται κατάταξη των δικτύων. Δεν απαιτείται ποτέ για τις συνήθεις εφαρμογές."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"περιορισμός αριθμού εκτελούμενων διαδικασιών"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Επιτρέπει στην εφαρμογή τον έλεγχο του μέγιστου αριθμού διαδικασιών που θα εκτελούνται. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"αναγκαστικός τερματισμός εφαρμογών στο παρασκήνιο"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας απομακρυσμένης οθόνης. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"σύνδεση σε μια υπηρεσία παρόχου δρομολογητή"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Δίνει στον κάτοχο τη δυνατότητα σύνδεσης με οποιονδήποτε εγγεγραμμένο πάροχο δρομολογητή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"σύνδεση σε μία είσοδο τηλεόρασης"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Αλλαγή κατάστασης WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Επιτρέπει στην εφαρμογή τη σύνδεση στο tablet και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Επιτρέπει στην εφαρμογή τη σύνδεση στο τηλέφωνο και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"κατάταξη δικτύων"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Επιτρέπει στην εφαρμογή να κατατάσσει τα δίκτυα και να επιλέγει τα προτιμώμενα δίκτυα του tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Επιτρέπει στην εφαρμογή να κατατάσσει τα δίκτυα και να επιλέγει τα προτιμώμενα δίκτυα του τηλεφώνου."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"σύζευξη με συσκευές Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο tablet, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο τηλέφωνο, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
@@ -1382,7 +1377,7 @@
<string name="vpn_lockdown_error" msgid="6009249814034708175">"Σφάλμα πάντα ενεργοποιημένου VPN"</string>
<string name="vpn_lockdown_config" msgid="6415899150671537970">"Αγγίξτε για διαμόρφωση"</string>
<string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
- <string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
+ <string name="no_file_chosen" msgid="6363648562170759465">"Δεν επιλέχθηκε κανένα αρχείο."</string>
<string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
<string name="submit" msgid="1602335572089911941">"Υποβολή"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Η λειτουργία αυτοκινήτου είναι ενεργοποιημένη"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c13bb1e..9e94287 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sync"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Too many <xliff:g id="CONTENT_TYPE">%s</xliff:g> deletions."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet storage is full. Delete some files to free space."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Watch storage is full. Delete some files to free up space."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Phone storage is full. Delete some files to free space."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Network may be monitored"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"By an unknown third party"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ringer on"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Shutting down…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Your tablet will shut down."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Your watch will shut down."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Your phone will shut down."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Do you want to shut down?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot to safe mode"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Allows the app to broadcast a notification that an SMS message has been received. Malicious apps may use this to forge incoming SMS messages."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-received broadcast"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Allows the app to broadcast a notification that a WAP PUSH message has been received. Malicious apps may use this to forge MMS message receipt or to silently replace the content of any web page with malicious variants."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"send score networks broadcast"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Allows the app to broadcast a notification that networks need to be scored. Never needed for normal apps."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limit number of running processes"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Allows the app to control the maximum number of processes that will run. Never needed for normal apps."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"force background apps to close"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind to a route provider service"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Allows the holder to bind to any registered route providers. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"change WiMAX state"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Allows the app to connect the phone to and disconnect the phone from WiMAX networks."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score networks"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Allows the app to rank networks and influence which networks the tablet should prefer."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Allows the app to rank networks and influence which networks the phone should prefer."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"pair with Bluetooth devices"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c13bb1e..9e94287 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sync"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Too many <xliff:g id="CONTENT_TYPE">%s</xliff:g> deletions."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet storage is full. Delete some files to free space."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Watch storage is full. Delete some files to free up space."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Phone storage is full. Delete some files to free space."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Network may be monitored"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"By an unknown third party"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ringer on"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Shutting down…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Your tablet will shut down."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Your watch will shut down."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Your phone will shut down."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Do you want to shut down?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot to safe mode"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Allows the app to broadcast a notification that an SMS message has been received. Malicious apps may use this to forge incoming SMS messages."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-received broadcast"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Allows the app to broadcast a notification that a WAP PUSH message has been received. Malicious apps may use this to forge MMS message receipt or to silently replace the content of any web page with malicious variants."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"send score networks broadcast"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Allows the app to broadcast a notification that networks need to be scored. Never needed for normal apps."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limit number of running processes"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Allows the app to control the maximum number of processes that will run. Never needed for normal apps."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"force background apps to close"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind to a route provider service"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Allows the holder to bind to any registered route providers. Should never be needed for normal apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"change WiMAX state"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Allows the app to connect the phone to and disconnect the phone from WiMAX networks."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score networks"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Allows the app to rank networks and influence which networks the tablet should prefer."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Allows the app to rank networks and influence which networks the phone should prefer."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"pair with Bluetooth devices"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b999506..337ab64 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que la aplicación transmita una notificación acerca de la recepción de un mensaje SMS. Las aplicaciones maliciosas pueden utilizar este permiso para falsificar mensajes SMS entrantes."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar emisiones WAP-PUSH-recibido"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que la aplicación transmita una notificación acerca de la recepción de un mensaje WAP PUSH. Las aplicaciones maliciosas pueden utilizar este permiso para falsificar la recepción de mensajes MMS o para reemplazar sin aviso el contenido de cualquier página web con variantes maliciosas."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmisión de puntuación de redes"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que la aplicación transmita una notificación que las redes necesitan para recibir una puntuación. Las aplicaciones normales no necesitan nunca este permiso."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar la cantidad de procesos en ejecución"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle la cantidad máxima de procesos que se ejecutarán. Las aplicaciones normales no deben utilizar este permiso."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones de fondo"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite al propietario vincularse a la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"vincular con un servicio de proveedor de rutas"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite al propietario vincular con proveedores de rutas registrados. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite enviar intentos a un administrador de dispositivos. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a una entrada de TV"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar el estado de WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte la tablet a una red WiMAX y que la desconecte de ella."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el dispositivo a una red WiMAX y que lo desconecte de ella."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar redes"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que la aplicación clasifique redes e influya en las redes que la tablet debería preferir."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que la aplicación clasifique redes e influya en las redes que el teléfono debería preferir."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación vea la configuración de Bluetooth de la tablet y que cree y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación vea la configuración de Bluetooth del dispositivo y que cree y acepte conexiones con los dispositivos sincronizados."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 24a919f..920bdbc 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronización"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Se ha agotado el espacio de almacenamiento del tablet. Elimina algunos archivos para liberar espacio."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"El almacenamiento del reloj está lleno. Elimina algunos archivos para liberar espacio."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Se ha agotado el espacio de almacenamiento del teléfono. Elimina algunos archivos para liberar espacio."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Es posible que la red esté supervisada"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por un tercero desconocido"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Timbre activado"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Apagando..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"El tablet se apagará."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"El reloj se apagará."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"El teléfono se apagará."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"¿Seguro que quieres apagar el teléfono?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar en modo seguro"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que la aplicación emita una notificación cuando se haya recibido un mensaje SMS. Las aplicaciones malintencionadas pueden usar este permiso para falsificar mensajes SMS entrantes."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar emisión recibida mediante mensaje WAP PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que la aplicación envíe una notificación cuando se haya recibido un mensaje WAP PUSH. Las aplicaciones malintencionadas pueden usar este permiso para falsificar la recepción de un mensaje MMS o para reemplazar sin aviso el contenido de cualquier página web con variantes malintencionadas."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar notificaciones sobre la puntuación de las redes"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que la aplicación emita una notificación que la red necesita para recibir una puntuación. Las aplicaciones normales no necesitan nunca este permiso."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar el número de procesos en ejecución"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle el número máximo de procesos que se ejecutarán. No es necesario nunca para las aplicaciones normales."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones en segundo plano"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite enlazar con la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite enlazar con la interfaz de nivel superior de un servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"enlazar con un servicio de proveedor de rutas"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite enlazar con proveedores de rutas registrados. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con el administrador de un dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que se envíen intentos a un administrador de dispositivos. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"enlazar a una entrada de TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar estado de WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte el tablet a redes WiMAX y lo desconecte de ellas."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el teléfono a redes WiMAX y lo desconecte de ellas."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar redes"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que la aplicación clasifique redes e influya en las redes que el tablet debe preferir."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que la aplicación clasifique una red e influya en las redes que el teléfono debe preferir."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación acceda a la configuración de Bluetooth del tablet y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación acceda a la configuración de Bluetooth del teléfono y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 92b7acb..222a06c 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sünkroonimine"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Liiga palju üksuse <xliff:g id="CONTENT_TYPE">%s</xliff:g> kustutusi."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tahvelarvuti mäluruum on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Kella talletusruum on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefonimälu on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Võrku võidakse jälgida"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Tundmatu kolmas osapool:"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Helin on sees"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Väljalülitamine ..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Teie tahvelarvuti lülitub välja."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Teie kell lülitub välja."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Teie telefon lülitub välja."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Kas soovite välja lülitada?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Ohutus režiimis taaskäivitamine"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Võimaldab rakendusel edastada teatise SMS-sõnumi vastuvõtmise kohta. Pahatahtlikud rakendused võivad seda kasutada sissetulevate SMS-sõnumite võltsimiseks."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"saada WAP-PUSH-vastuvõetud saateid"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Võimaldab rakendusel edastada teatise WAP PUSH-sõnumi vastuvõtmise kohta. Pahatahtlikud rakendused võivad seda kasutada MMS-sõnumite vastuvõtmise võltsimiseks või mis tahes veebilehe sisu salaja asendamiseks pahatahtlikuga."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"võrkude levi hinnangu saatmine"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Lubab rakendusel levitada märguannet, et võrke tuleb hinnata. Seda ei ole kunagi vaja tavapäraste rakenduste puhul."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"piira töötavate protsesside arvu"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Võimaldab rakendusel juhtida töötavate protsesside maksimaalset arvu. Tavarakenduste puhul pole seda vaja."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"sundige taustarakendused sulguma"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lubab omanikul siduda rakenduse kaugekraani ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vidinateenusega sidumine"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"sidumine marsruudi pakkumisteenusega"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Lubab õiguste omajal luua seosed kõikide registreeritud marsruutide pakkujatega. Pole kunagi vajalik tavaliste rakenduste korral."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Võimaldab omanikul saata kavatsusi seadme administraatorile. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"sidumine TV-sisendiga"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-i oleku muutmine"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Võimaldab rakendusel luua ja katkestada tahvelarvuti ühenduse WiMAX-i võrkudega."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Võimaldab rakendusel luua ja katkestada telefoni ühenduse WiMAX-i võrkudega."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"võrkude hindamine"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Lubab rakendusel võrke hinnata ja mõjutada seda, milliseid võrke peaks tahvelarvuti eelistama."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Lubab rakendusel võrke hinnata ja mõjutada seda, milliseid võrke peaks telefon eelistama."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"siduge Bluetoothi seadmetega"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Võimaldab rakendusel vaadata tahvelarvuti Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Võimaldab rakendusel vaadata telefoni Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index cf2f957..300dfcd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگامسازی"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"حافظه رایانهٔ لوحی پر است! برخی از فایلها را حذف کنید تا فضا آزاد شود."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"حافظه ساعت پر است. برای آزادسازی فضا، چند فایل را حذف کنید."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"حافظه تلفن پر است. بعضی از فایلها را حذف کنید تا فضا آزاد شود."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ممکن است شبکه نظارت شده باشد"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"توسط یک شخص ثالث ناشناس"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"زنگ روشن"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"در حال خاموش شدن…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش میشود."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ساعت شما خاموش میشود."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش میشود."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"آیا میخواهید تلفن خاموش شود؟"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"راهاندازی مجدد در حالت امن"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"به برنامه اجازه میدهد تا اعلان دریافت پیام کوتاه را پخش کند. برنامههای مخرب میتوانند از این برای جعل پیامهای کوتاه ورودی استفاده کنند."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ارسال پخش دریافت شده توسط WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"به برنامه اجازه میدهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامههای مخرب میتوانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحهٔ وب را با انواع مخرب جایگزین کنند."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ارسال اعلان پخش برای امتیازبندی شبکهها"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"به برنامه اجازه میدهد تا اعلانی پخش کند که شبکهها باید امتیازبندی شوند. هرگز برای برنامههای عادی مورد نیاز نیست."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"محدود کردن تعداد فرآیندهای در حال اجرا"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"به برنامه اجازه میدهد تا حداکثر تعداد پردازشهایی را که اجرا خواهد شد کنترل کند. هرگز برای برنامههای عادی لازم نیست."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"بستن اجباری برنامههای پسزمینه"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"به دارنده امکان میدهد تا به رابط سطح بالای نمایشگر راه دور وصل شود. نباید هرگز برای برنامههای عادی لازم باشد."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"به دارنده اجازه میدهد که به رابط سطح بالای سرویس ابزارک متصل شود. هرگز برای برنامههای معمولی مورد نیاز نیست."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"اتصال به یک سرویس ارائهدهنده مسیر"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"به دارنده امکان میدهد به هر ارائهدهنده مسیر ثبت شدهای متصل شود. هرگز برای برنامههای عادی مورد نیاز نیست."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"تعامل با یک سرپرست دستگاه"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"به دارنده اجازه میدهد اهداف خود را به سرپرست دستگاه ارسال کند. برنامههای معمولی هیچگاه به این ویژگی نیازی ندارند."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"اتصال به ورودی تلویزیون"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"تغییر وضعیت WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان میدهد رایانهٔ لوحی را به شبکههای وایمکس متصل کرده یا اتصال آن را از این شبکهها قطع کند."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"به برنامه امکان میدهد تا تلفن را به شبکههای وایمکس متصل کرده یا اتصال آنرا از این شبکهها قطع کند."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"امتیازبندی شبکهها"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"به برنامه اجازه میدهد که شبکهها را درجهبندی کند و روی اینکه رایانه لوحی باید کدام شبکه را در اولویت قرار دهد تأثیر میگذارد."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"به برنامه اجازه میدهد که شبکهها را درجهبندی کند و روی اینکه تلفن باید کدام شبکه را در اولویت قرار دهد تأثیر میگذارد."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"جفت کردن با دستگاههای بلوتوث"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"به برنامه اجازه میدهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاههای مرتبط را برقرار کرده و بپذیرد."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 4d11ad4..9202e0d 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Sallii sovelluksen lähettää ilmoituksen tekstiviestin vastaanotosta. Haitalliset sovellukset voivat käyttää tätä saapuvien tekstiviestien väärentämiseen."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"lähetä WAP-PUSH-vastaanotettu lähetys"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Antaa sovelluksen lähettää ilmoituksen WAP PUSH -viestin vastaanotosta. Haitalliset sovellukset voivat käyttää tätä MMS-viestien vastaanoton väärentämiseen tai sivujen sisällön korvaamiseen huomaamattomasti haitallisella sisällöllä."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"lähetä verkkojen pisteet"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Sallii sovelluksen lähettää ilmoituksen verkon pisteytystarpeesta. Ei tarvita tavallisissa sovelluksissa."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"rajoita käynnissä olevien prosessien määrää"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Antaa sovelluksen hallita suoritettavien sovellusten enimmäismäärää. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pakota taustasovelluksia sulkeutumaan"</string>
@@ -392,6 +390,10 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Antaa sovelluksen sitoutua etänäytön ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Antaa sovelluksen sitoutua widget-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+ <!-- no translation found for permlab_bindRouteProvider (4869394607915096847) -->
+ <skip />
+ <!-- no translation found for permdesc_bindRouteProvider (4703804520859960329) -->
+ <skip />
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikoi laitteen järjestelmänvalvojan kanssa"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Antaa sovelluksen lähettää aikomuksia laitteen järjestelmänvalvojalle. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"sido TV-tuloon"</string>
@@ -642,12 +644,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Vaihda WiMAX-verkon tilaa"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Antaa sovelluksen muodostaa tablet-laitteella yhteyden WiMAX-verkkoon ja katkaista yhteyden."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Antaa sovelluksen muodostaa puhelimella yhteyden WiMAX-verkkoon ja katkaista yhteyden."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"pisteytä verkot"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Sallii sovelluksen asettaa verkkoja paremmuusjärjestykseen ja vaikuttaa siihen, mikä verkko tablet-laitteen kannattaa valita."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Sallii sovelluksen asettaa verkkoja paremmuusjärjestykseen ja vaikuttaa siihen, mikä verkko puhelimen kannattaa valita."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"muodosta laitepari Bluetooth-laitteiden kanssa"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Antaa sovelluksen tarkastella tablet-laitteen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Antaa sovelluksen tarkastella puhelimen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä muihin laitteisiin."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d2f4c9b..5e2cb28 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchroniser"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"La mémoire de la tablette est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"La mémoire de la montre est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Le réseau peut être surveillé"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Par un tiers inconnu"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Sonnerie activée"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Votre tablette va s\'éteindre."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Votre montre va s\'éteindre."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Voulez-vous éteindre l\'appareil?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Redémarrer en mode sans échec"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message texte. Des applications malveillantes peuvent utiliser cette fonctionnalité pour créer de faux messages entrants."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"envoyer une diffusion de réception de WAP par poussée"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message WAP par poussée. Des applications malveillantes peuvent utiliser cette fonctionnalité pour créer de faux messages multimédias entrants ou pour remplacer le contenu d\'une page Web par du contenu malveillant."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"diffuser le classement des réseaux"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Autorise l\'application à diffuser une notification signalant que les réseaux doivent être évalués. Cela n\'est jamais nécessaire pour les applications normales."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"restreindre le nombre de processus en cours d\'exécution"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet à l\'application de définir le nombre maximal de processus devant s\'exécuter. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forcer la fermeture des applications en arrière-plan"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un écran distant. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"s\'associer à un service de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"associer à un fournisseur d\'itinéraires enregistré"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permet à l\'application autorisée de s\'associer à des fournisseurs d\'itinéraires enregistrés. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur d\'un périphérique"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"s\'associer à une entrée de téléviseur"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifier l\'état du WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"classer les réseaux"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Autorise l\'application à classer les réseaux et à influencer la sélection du réseau par la tablette."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Autorise l\'application à classer les réseaux et à influencer la sélection du réseau par le téléphone."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"s\'associer à des appareils Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7a42a6d..6435652 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisation"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"La mémoire de la tablette est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"La mémoire de la montre est saturée. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Il est possible que le réseau soit surveillé."</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Par un tiers inconnu"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Sonnerie activée"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Votre tablette va s\'éteindre."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"La montre va s\'éteindre."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Voulez-vous éteindre l\'appareil ?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Redémarrer en mode sans échec"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un SMS. Des applications malveillantes peuvent exploiter cette fonctionnalité pour créer de faux SMS entrants."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Envoi de diffusion de réception de WAP PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message WAP PUSH. Des applications malveillantes peuvent exploiter cette fonctionnalité pour créer de faux MMS entrants ou pour remplacer le contenu d\'une page Web par du contenu malveillant."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"diffuser des notifications pour l\'évaluation des réseaux"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Autoriser l\'application à diffuser une notification signalant que les réseaux doivent être évalués. Cette autorisation n\'est pas nécessaire pour les applications standards."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"Nombre maximal de processus en cours d\'exécution"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet à l\'application de contrôler le nombre maximal de processus devant s\'exécuter. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forcer la fermeture des applications en arrière-plan"</string>
@@ -361,7 +357,7 @@
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Permet à l\'application de lancer l\'interface utilisateur de confirmation de sauvegarde complète. Seules certaines applications peuvent bénéficier de cette permission."</string>
<string name="permlab_internalSystemWindow" msgid="2148563628140193231">"Affichage de fenêtres non autorisées"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permet à l\'application de créer des fenêtres destinées à être utilisées par l\'interface utilisateur du système interne. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
- <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"S\'afficher en surimpression dans les autres applis"</string>
+ <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"Se superposer aux autres applis"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permet à l\'application d\'ignorer d\'autres applications ou certaines parties de l\'interface utilisateur. Cela peut altérer votre utilisation de l\'interface de n\'importe quelle application, ou modifier ce que vous pensez voir dans d\'autres applications."</string>
<string name="permlab_setAnimationScale" msgid="2805103241153907174">"Réglage de la vitesse des animations"</string>
<string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permet à l\'application de modifier à tout moment la vitesse générale des animations pour les ralentir ou les accélérer."</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permettre à l\'application autorisée de s\'associer à l\'interface de niveau supérieur d\'un écran à distance. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"s\'associer à un fournisseur d\'itinéraires"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permettre à l\'application autorisée de s\'associer à n\'importe quel fournisseur d\'itinéraires. Ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur du périphérique"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"s\'associer à une entrée TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifier l\'état du WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"évaluer les réseaux"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Autoriser l\'application à classer les réseaux et à influencer la sélection du réseau sur la tablette"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Autoriser l\'application à classer les réseaux et à influencer la sélection du réseau sur le téléphone"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"associer à des appareils Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index dc298de..831b327 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"समन्वयन"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"बहुत से <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटाए जाते हैं."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"टेबलेट संग्रहण भर गया है. स्थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"घड़ी संग्रहण भर गया है. स्थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"फ़ोन संग्रहण भर गया है. स्थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"किसी अज्ञात तृतीय पक्ष के द्वारा"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"रिंगर चालू"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"शट डाउन हो रहा है..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"आपकी टेबलेट शट डाउन हो जाएगी."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"आपकी घड़ी बंद हो जाएगी."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"आपका फ़ोन शट डाउन हो जाएगा."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"क्या आप शट डाउन करना चाहते हैं?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"सुरक्षित मोड में रीबूट करें"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ऐप्स को वह सूचना प्रसारित करने देता है जो SMS संदेश ने प्राप्त की है. दुर्भावनापूर्ण ऐप्स इसका उपयोग नकली इनकमिंग संदेश गढ़ने के लिए कर सकते हैं."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-प्राप्त प्रसारण भेजें"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ऐप्स को वह सूचना प्रसारित करने देता है जो WAP PUSH संदेश को प्राप्त हुआ है. दुर्भावनापूर्ण ऐप्स इसका उपयोग नकली MMS संदेश प्राप्त करने या किसी वेबपृष्ठ की सामग्री को दुर्भावनापूर्ण दूसरे रूप से चुपचाप प्रतिस्थापित करने के लिए कर सकते हैं."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"स्कोर नेटवर्क प्रसारण भेजें"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ऐप्स को यह सूचना प्रसारित करने देती है कि नेटवर्क को स्कोर किए जाने की आवश्यकता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"चल रही प्रक्रियाओं की संख्या सीमित करें"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ऐप्स को चलाई जाने वाली अधिकतम प्रक्रियाओं को नियंत्रित करने देता है. सामान्य ऐप्स के लिए कभी आवश्यक नहीं होती."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"पृष्ठभूमि ऐप्स को बलपूर्वक बंद करें"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"धारक को किसी रिमोट डिस्प्ले के शीर्ष-स्तरीय इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"किसी विजेट सेवा से आबद्ध करें"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"किसी रूट प्रदाता सेवा से आबद्ध हों"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"धारक को किसी भी पंजीकृत रूट प्रदाता से आबद्ध रहने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्यवस्थापक के साथ सहभागिता करें"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्यवस्थापक को उद्देश्य भेजने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"टीवी इनपुट से आबद्ध करें"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX स्थिति बदलें"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ऐप्स को WiMAX नेटवर्क से टेबलेट को कनेक्ट और डिस्कनेक्ट करने देता है."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ऐप्स को WiMAX नेटवर्क से फ़ोन को कनेक्ट और डिस्कनेक्ट करने देता है."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"स्कोर नेटवर्क"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ऐप्स को नेटवर्क को रैंक करने देती है और इस बात पर ज़ोर देती है कि टेबलेट को किस नेटवर्क को प्राथमिकता देनी चाहिए."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ऐप्स को नेटवर्क को रैंक करने देती है और इस बात पर ज़ोर देती है कि फ़ोन को किस नेटवर्क को प्राथमिकता देनी चाहिए."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth उपकरणों के साथ युग्मित करें"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ऐप्स को टेबलेट पर Bluetooth का कॉन्फ़िगरेशन देखने, और युग्मित उपकरणों के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ऐप्स को फ़ोन पर Bluetooth का कॉन्फ़िगरेशन देखने, और युग्मित उपकरणों के साथ कनेक्शन बनाने और स्वीकार करने देता है."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 96872e8..40b194c 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkronizacija"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše brisanja stavki <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Prostor za pohranu tabletnog računala pun je. Izbrišite nekoliko datoteka kako biste oslobodili prostor."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Pohrana sata puna je. Izbrišite neke datoteke da biste oslobodili prostor."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Prostor za pohranu na telefonu je pun. Izbrišite nekoliko datoteka kako biste oslobodili prostor."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mreža se možda nadzire"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Zvono uključeno"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Isključivanje..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Vaš tabletni uređaj će se isključiti."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Sat će se isključiti."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Vaš će se telefon isključiti."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Želite li isključiti uređaj?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Ponovno pokretanje u sigurnom načinu rada"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Omogućuje aplikaciji emitiranje obavijesti da je primljena SMS poruka. Zlonamjerne aplikacije mogu to upotrijebiti za krivotvorenje dolaznih SMS poruka."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"slanje WAP-PUSH-primljenih prijenosa"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Omogućuje aplikaciji emitiranje obavijesti da je primljena WAP PUSH poruka. Zlonamjerne aplikacije mogu to upotrijebiti da bi krivotvorile prijem MMS poruka ili da bi potajno zamijenile sadržaj bilo koje web-stranice zlonamjernim varijantama."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"slanje obavijesti za ocjenjivanje mreža"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Aplikaciji omogućuje emitiranje obavijesti da se mreža treba ocijeniti. Nije potrebno za normalne aplikacije."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ograničavanje broja pokrenutih postupaka"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Omogućuje aplikaciji upravljanje maksimalnim brojem postupaka koji će biti pokrenuti. Nikada nije potrebno za uobičajene aplikacije."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"prisilno zatvaranje pozadinskih aplikacija"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Nositelju omogućuje vezanje uza sučelje najviše razine udaljenog zaslona. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"povezivanje s davateljem usluge usmjeravanja poziva"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Nositelju omogućuje povezivanje s registriranim davateljem usluga usmjeravanja poziva. Nije potrebno za normalne aplikacije."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Nositelju omogućuje slanje namjera administratoru uređaja. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"povezivanje s TV ulazom"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Promjena stanja WiMAX mreže"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogućuje povezivanje tabletnog računala s WiMAX mrežama i prekidanje veze tabletnog računala s njima."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Aplikaciji omogućuje povezivanje telefona s WiMAX mrežama i prekidanje veze telefona s njima."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocjenjivanje mreža"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Aplikaciji omogućuje rangiranje mreža i utjecanje na odabir preferiranih mreža na tabletu."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Aplikaciji omogućuje rangiranje mreža i utjecanje na odabir preferiranih mreža na telefonu."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"uparivanje s Bluetooth uređajima"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index aded23b..7c95b53 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Szinkronizálás"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Túl sok <xliff:g id="CONTENT_TYPE">%s</xliff:g> törlés."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"A táblagép tárhelye tele van. Szabadítson fel helyet néhány fájl törlésével."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Az óra tárhelye megtelt. Szabadítson fel helyet néhány fájl törlésével."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"A telefon tárhelye megtelt. Hely felszabadításához töröljön néhány fájlt."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Lehet, hogy a hálózat felügyelt"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ismeretlen harmadik fél által"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Csengő bekapcsolva"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Leállítás..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"A táblagép ki fog kapcsolni."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Az óra ki fog kapcsolni."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"A telefon le fog állni."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Kikapcsolja?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Újraindítás csökkentett módban"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Lehetővé teszi az alkalmazás számára értesítés küldését SMS érkezéséről. A rosszindulatú alkalmazások beérkező SMS-ek hamisítására használhatják fel ezt."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH alapú üzenetek küldése"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Lehetővé teszi az alkalmazás számára értesítés küldését WAP PUSH üzenet érkezése esetén. A rosszindulatú alkalmazások arra használhatják ezt, hogy MMS-kézbesítési jelentést hamisítsanak, vagy hogy a háttérben rosszindulatú variánssal cseréljék le bármelyik weboldal tartalmát."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"hálózatpontozási értesítés küldése"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Lehetővé teszi, hogy az alkalmazás szétküldjön egy értesítést, amely szerint a hálózatokat pontozni kell. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"futó folyamatok számának korlátozása"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lehetővé teszi az alkalmazás számára a futtatható folyamatok maximális számának vezérlését. Soha nem lehet rá szüksége a normál alkalmazásoknak."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"háttéralkalmazások leállításának kényszerítése"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lehetővé teszi a használó számára, hogy csatlakozzon egy távoli kijelző legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"csatlakozás egy útvonal-szolgáltatóhoz"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Az eszköz kezelője csatlakozhat bármely regisztrált útvonal-szolgáltatóhoz. A normál alkalmazások esetében erre nincs szükség."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lehetővé teszi a tulajdonos számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"csatlakozás tévébemenethez"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-állapot módosítása"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lehetővé teszi az alkalmazás számára, hogy a táblagépet csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lehetővé teszi az alkalmazás számára, hogy a telefont csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"hálózatok pontozása"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Lehetővé teszi, hogy az alkalmazás rangsorolja a hálózatokat, illetve befolyásolja, hogy a táblagép mely hálózatokat részesítse előnyben."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Lehetővé teszi, hogy az alkalmazás rangsorolja a hálózatokat, illetve befolyásolja, hogy a telefon mely hálózatokat részesítse előnyben."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth-eszközök párosítása"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lehetővé teszi az alkalmazás számára a táblagépen lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Lehetővé teszi az alkalmazás számára a telefonon lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 9edccf8..c788068 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Թույլ է տալիս հավելվածին հաղորդել ծանուցում, որ ստացվել է SMS հաղորդագրություն: Վնասարար հավելվածները կարող են օգտագործել սա` կեղծելու մուտքային SMS հաղորդագրությունները:"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ուղարկել ստացված WAP-PUSH-ի հաղորդում"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Թույլ է տալիս հավելվածին հաղորդել ծանուցում, որ ստացվել է WAP PUSH հաղորդագրություն: Վնասարար հավելվածները կարող են օգտագործել սա` կեղծելու MMS հաղորդագրության ստացումը կամ աննկատ փոխարինելու ցանկացած կայքի բովանդակությունը վնասարար տարբերակներով:"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ուղարկել ցանցերի գնահատականի հեռարձակում"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ծրագրին թույլ է տալիս հեռարձակել ծանուցում, որ ցանցերը պետք է հաշվարկվեն: Նորմալ ծրագրերում երբեք պետք չի գալիս:"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"սահմանափակել աշխատող գործընթացների թիվը"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Թույլ է տալիս հավելվածին վերահսկել գործընթացների առավելագույն թիվը, որ աշխատելու են: Երբևէ անհրաժեշտ չէ սովորական հավելվածների համար:"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"ստիպել, որ առաջին պլանի հավելվածները փակվեն"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Թույլ է տալիս սեփականատիրոջը միանալ հեռակա էկրանի վերին մակարդակի ինտերֆեյսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"միանալ վիջեթ ծառայությանը"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Թույլ է տալիս սեփականատիրոջը միանալ վիջեթ ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"կապվել երթուղու մատակարարի ծառայությանը"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Թույլ է տալիս տիրոջը կապվել երթուղու մատակարարներից ցանկացածին: Սովորական ծրագրերի համար երբեք անհրաժեշտ չէ:"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"փոխգործակցել սարքի կառավարչի հետ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Թույլ է տալիս սեփականատիրոջը ուղարկել մտադրություններ սարքի կառավարչին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"միանալ հեռուստացույցի մուտքին"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Փոխել WiMAX-ի կարգավիճակը"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Թույլ է տալիս հավելվածին գրասալիկը միացնել WiMAX ցանցին և անջատվել այդ ցանցից:"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Թույլ է տալիս հավելվածին հեռախոսը միացնել WiMAX ցանցին և անջատել այդ ցանցից:"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ցանցերի գնահատական"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ծրագրին թույլ է տալիս դասակարգել ցանցերը և ազդել գրասալիկի նախընտրելի ցանցի ընտրության գործընթացի վրա:"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ծրագրին թույլ է տալիս դասակարգել ցանցերը և ազդել հեռախոսի նախընտրելի ցանցի ընտրության գործընթացի վրա:"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"զուգակցվել Bluetooth սարքերի հետ"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը գրասալիկի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը հեռախոսի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index be0730a..a7ede78 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkron"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak <xliff:g id="CONTENT_TYPE">%s</xliff:g> penghapusan."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Penyimpanan tablet penuh. Hapus beberapa file untuk mengosongkan ruang."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Penyimpanan arloji penuh. Hapus beberapa file untuk mengosongkan ruang."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Penyimpanan di ponsel penuh. Hapus sebagian file untuk mengosongkan ruang."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Jaringan mungkin dipantau"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Oleh pihak ketiga yang tidak dikenal"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Pendering nyala"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Sedang mematikan..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet Anda akan dimatikan."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Arloji Anda akan dimatikan."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ponsel Anda akan dimatikan."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Anda ingin mematikannya?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot ke mode aman"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Mengizinkan apl menyiarkan pemberitahuan bahwa pesan SMS telah diterima. Apl berbahaya dapat menggunakan ini untuk memalsukan pesan SMS masuk."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"kirim siaran WAP-PUSH-diterima"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Mengizinkan apl menyiarkan pemberitahuan bahwa pesan WAP PUSH telah diterima. Apl berbahaya dapat menggunakan ini untuk memalsukan penerimaan pesan MMS atau diam-diam mengganti konten laman web apa pun dengan varian berbahaya."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"mengirim siaran beri skor jaringan"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Memungkinkan aplikasi menyiarkan pemberitahuan bahwa jaringan perlu diberi skor. Tidak pernah diperlukan untuk aplikasi normal."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"batasi jumlah dari proses yang berjalan"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Mengizinkan apl mengontrol jumlah maksimum proses yang akan berjalan. Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"paksa aplikasi latar belakang agar menutup"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Mengizinkan pemegang mengikat ke antarmuka tingkat atas dari layar jarak jauh. Tidak pernah diperlukan untuk aplikasi normal."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"mengikat ke layanan penyedia rute"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Memungkinkan pemegang mengikat ke penyedia rute terdaftar mana pun. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"mengikat ke masukan TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Ubah status WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"memberi skor jaringan"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Memungkinkan aplikasi menilai jaringan dan memengaruhi jaringan mana yang sebaiknya dipilih tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Memungkinkan aplikasi menilai jaringan dan memengaruhi jaringan mana yang sebaiknya dipilih ponsel."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"sandingkan dengan perangkat Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1ef77de..4c3d8a3 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizzazione"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Troppe eliminazioni di <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Spazio di archiviazione del tablet esaurito. Elimina alcuni file per liberare spazio."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"La memoria dell\'orologio è piena. Elimina alcuni file per liberare spazio."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Spazio di archiviazione del telefono esaurito. Elimina alcuni file per liberare spazio."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"La rete potrebbe essere monitorata"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Da una terza parte sconosciuta"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Suoneria attiva"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Spegnimento..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Il tablet verrà spento."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"L\'orologio verrà spento."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Il telefono verrà spento."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Spegnere?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Riavvia in modalità provvisoria"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Consente all\'applicazione di trasmettere una notifica che informa della ricezione di un messaggio SMS. Le applicazioni dannose potrebbero farne uso per creare messaggi SMS in arrivo."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"invio broadcast ricevuti tramite WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Consente all\'applicazione di trasmettere una notifica che informa della ricezione di un messaggio WAP PUSH. Le applicazioni dannose potrebbero farne uso per simulare la ricezione di messaggi MMS o per sostituire di nascosto i contenuti di qualsiasi pagina web con varianti dannose."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"invio trasmissione classificazione reti"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Consente all\'app di trasmettere una notifica indicante che le reti devono essere classificate. Opzione non necessaria per le app normali."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"numero limite di processi in esecuzione"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Consente all\'applicazione di controllare il numero massimo di processi che verranno eseguiti. Mai necessaria per le applicazioni normali."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"chiusura forzata applicazioni di background"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un display remoto. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Consente l\'associazione all\'interfaccia principale di un servizio widget. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"collegamento a un servizio provider di routing"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Consente al titolare di collegarsi a qualsiasi provider di routing registrato. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interazione con un amministratore dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Consente l\'invio di intent a un amministratore del dispositivo. L\'autorizzazione non dovrebbe mai essere necessaria per le normali applicazioni."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"collegamento a ingresso TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifica stato WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Consente all\'applicazione di connettere/disconnettere il tablet dalle reti WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Consente all\'applicazione di connettere/disconnettere il telefono dalle reti WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"valutazione reti"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Consente all\'app di stilare una classifica delle reti e determinare quali di queste il tablet deve prediligere."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Consente all\'app di stilare una classifica delle reti e determinare quali di queste il telefono deve prediligere."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"accoppiamento con dispositivi Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul tablet e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul telefono e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index f343f4a..f818574 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"סינכרון"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"יש מחיקות רבות מדי של <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"שטח האחסון של הטאבלט מלא. מחק קבצים כדי לפנות מקום."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"שטח האחסון של השעון מלא. מחק כמה קבצים כדי לפנות שטח."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"שטח האחסון של הטלפון מלא. מחק חלק מהקבצים כדי לפנות שטח."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ייתכן שהרשת מנוטרת"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"על ידי צד שלישי לא מוכר"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"צלצול מופעל"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"מכבה..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטאבלט שלך יכבה."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"השעון יכבה."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"הטלפון שלך יכובה."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"האם ברצונך לבצע כיבוי?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"אתחל למצב בטוח"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"מאפשר לאפליקציה לשדר התראה על כך שהתקבלה הודעת SMS. אפליקציות זדוניות עלולות להשתמש בכך כדי לזייף הודעות SMS נכנסות."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"שלח שידור שהתקבל באמצעות WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"מאפשר לאפליקציה לשדר התראה על כך שהתקבלה הודעה מסוג WAP PUSH. אפליקציות זדוניות עלולות להשתמש בכך כדי לזייף קבלה של הודעות MMS או כדי להחליף בחשאי את התוכן של דף אינטרנט כלשהו בגירסאות זדוניות."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"שלח שידור לדירוג רשתות"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"מאפשר לאפליקציה לשדר התראה על כדי שיש לדרג את הרשתות. לא בשימוש עבור אפליקציות רגילות."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"הגבל את מספר התהליכים הפועלים"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"מאפשר לאפליקציה לשלוט על המספר המרבי של תהליכים שיפעלו. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"אילוץ סגירה של אפליקציות ברקע"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של צג רחוק. לעולם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"הכפפה לשירות Widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"איגוד לשירות של ספק ניתוב"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"מאפשרת לבעלים לאגד לספקי ניתוב רשומים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"מאפשר למשתמש לשלוח כוונות למנהל התקנים. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"איגוד לקלט טלוויזיה"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"שנה את מצב WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"מאפשר לאפליקציה לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"מאפשר לאפליקציה לחבר את הטלפון לרשתות WiMAX ולהתנתק מהן."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"דרג רשתות"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"מאפשר ליישום לדרג רשתות ולהשפיע על הרשתות שאותן הטאבלט יעדיף."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"מאפשר ליישום לדרג רשתות ולהשפיע על הרשתות שאותן הטלפון יעדיף."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"התאמה למכשירי Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטאבלט, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטלפון, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 501fb81..159a19e 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同期"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>での削除が多すぎます。"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"タブレットのストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ウォッチのストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"端末のストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ネットワークが監視される場合があります"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"不明な第三者"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"着信音オン"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"シャットダウン中..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"タブレットの電源をOFFにします。"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ウォッチの電源をOFFにします。"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"携帯電話の電源を切ります。"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"シャットダウンしますか?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"再起動してセーフモードに変更"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"SMSメッセージの受信通知の配信をアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、受信SMSメッセージが偽造される恐れがあります。"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH受信ブロードキャストの送信"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"WAP PUSHメッセージの受信通知を配信することをアプリに許可します。この許可を悪意のあるアプリに利用されると、MMSメッセージの受信確認が偽造されたりウェブページのコンテンツが悪意のあるコンテンツに密かに置き換えられたりする恐れがあります。"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ネットワークスコアのブロードキャスト送信"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ネットワークのスコアリングが必要であるという通知をブロードキャスト送信することをアプリに許可します。通常のアプリでは不要です。"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"実行中のプロセスの数を制限"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"実行するプロセスの上限数を制御することをアプリに許可します。通常のアプリでは不要です。"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"バックグラウンドのアプリの強制終了"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"リモートディスプレイのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ウィジェットサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ルートプロバイダサービスへのバインド"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"登録済みのルートプロバイダにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"デバイス管理者との通信"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"デバイス管理者へのintentの送信を所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"テレビの入力へのバインド"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX状態の変更"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"タブレットのWiMAXネットワークへの接続と切断をアプリに許可します。"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"携帯端末のWiMAXネットワークへの接続と切断をアプリに許可します。"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ネットワークスコア"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ネットワークを順位付けし、タブレットでのネットワークの優先順位に反映することをアプリに許可します。"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ネットワークを順位付けし、携帯電話でのネットワークの優先順位に反映することをアプリに許可します。"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetoothデバイスのペアの設定"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"タブレットのBluetooth設定を表示すること、ペアの端末に接続すること/ペアの端末からの接続を受け入れることをアプリに許可します。"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"携帯端末のBluetooth設定を表示すること、ペアの端末に接続すること/ペアの端末からの接続を受け入れることをアプリに許可します。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 5f7fa89..db9088c 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"სინქრონიზაცია"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>-ის ძალიან ბევრი წაშლილები."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"ტაბლეტის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"საათის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"ტელეფონის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"შესაძლოა ქსელი მონიტორინგის ქვეშ იმყოფება"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"უცნობი მესამე მხარის მიერ"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"ზარი ჩართულია"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"გამორთვა…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"თქვენი ტაბლეტი გაითიშება."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"თქვენი საათი გაითიშება."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"თქვენი ტელეფონი გაითიშება."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"გსურთ გამორთვა?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"უსაფრთხო რეჟიმის ჩატვირთვა"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"აპს საშუალებას აძლევს გააგზავნოს შეტყობინება SMS შეტყობინების მიღების თაობაზე. მავნე აპლიკაციებში ეს ფუნქცია შეიძლება გამოყენებული იქნას SMS შეტყობინებების მიღების იმიტაციიისათვის."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-ით მიღებული სამაუწყებლო შეტყობინების გაგზავნა"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"აპს შეეძლება, გაგზავნოს შეტყობინება WAP PUSH შეტყობინების მიღების თაობაზე. მავნე აპებმა ეს შეიძლება გამოიყენონ MMS შეტყობინების მიღების გასაყალბებლად ან ნებისმიერი ვებგვერდის კონტენტის სახიფათო ვარიანტებით ჩუმად ჩასანაცვლებლად."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ქსელის შეფასებების მაუწყებლობის გაგზავნა"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"აპს ნებას რთავს გადასცეს შეტყობინება, რომ ქსელები შეფასებას საჭიროებს. ჩვეულებრივ აპებს ეს არასოდეს ჭირდება."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"მიმდინარე პროცესების რაოდენობის ლიმიტი"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"აპს შეეძლება, გააკონტროლოს მიმდინარე პროცესების მაქსიმალური რაოდენობა. ჩვეულებრივ აპებში არასდროს არის საჭირო."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"უკანა ფონის აპის იძულებით დახურვა"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"მფლობელს შეეძლება მიებას დისტანციურ მონიტორის ზედა დონის ინტერფეისს. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ვიჯეტ სერვისთან დაკავშირება"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"აპს შეეძლება ზედა დონის ინტერფეისის ვიჯეტთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"მარშრუტის სერვისის პროვაიდერთან შეკავშირება"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"საშუალებას აძლევს მფლობელს შეკავშირდეს მარშრუტების ნებისმიერ პროვაიდერთან. ჩვეულებრივ აპებს უმეტეს შემთხვევაში არ დაჭირდება."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"მოწყობილობის ადმინთან ინტერაქცია"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"აპს შეეძლება მოწყობილობის ადმინისტრატორისთვის intent ობიექტების გაგზავნა. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"TV შეყვანასთან მიბმა"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX მდგომარეობის შეცვლა"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტაბლეტი WiMAX ქსელებიდან."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტელეფონი WiMAX ქსელებიდან."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ქსელების შეფასება"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"აპს ნებას რთავს შეაფასოს ქსელები და იქონიოს ზეგავლენა, თუ რომელი ქსელი ამჯობინოს ტაბლეტმა."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"აპს ნებას რთავს შეაფასოს ქსელები და იქონიოს ზეგავლენა, თუ რომელი ქსელი ამჯობინოს ტელეფონმა."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth მოწყობილობებთან დაწყვილება"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტაბლეტზე, შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტელეფონზე და შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 45389f7..7eb674a 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ធ្វើសមកាលកម្ម"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"មានការលុប <xliff:g id="CONTENT_TYPE">%s</xliff:g> ច្រើនពេក។"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"ឧបករណ៍ផ្ទុកនៃកុំព្យូទ័របន្ទះពេញ។ លុបឯកសារមួយចំនួន។"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ឧបករណ៍របស់នាឡិកាពេញ។ លុបឯកសារមួយចំនួន។"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"ឧបករណ៍ផ្ទុកទូរស័ព្ទពេញ! លុបឯកសារមួយចំនួនដើម្បីបង្កើនទំហំ។"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"បណ្ដាញអាចត្រូវបានតាមដាន"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ដោយភាគីទីបីដែលមិនស្គាល់"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"បើកកម្មវិធីរោទ៍"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"កំពុងបិទ..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"កុំព្យូទ័របន្ទះរបស់អ្នកនឹងបិទ។"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"នាឡិការបស់អ្នកនឹងបិទ។"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"ទូរស័ព្ទរបស់អ្នកនឹងបិទ។"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"តើអ្នកចង់បិទ?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"ចាប់ផ្ដើមឡើងវិញដើម្បីចូលរបៀបសុវត្ថិភាព"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ឲ្យកម្មវិធីប្រកាសការជូនដំណឹងការទទួលសារ SMS ។ កម្មវិធីព្យាបាទអាចប្រើវាដើម្បីបន្លំសារ SMS ចូល។"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ផ្ញើការប្រកាសបានទទួល WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ឲ្យកម្មវិធីប្រកាសការជូនដំណឹងថាបានទទួលសារ WAP PUSH ។ កម្មវិធីព្យាបាទអាចប្រើវាដើម្បីក្លែងបង្កាន់ដៃសារ MMS ឬជំនួសមាតិកាទំព័របណ្ដាញណាមួយស្ងាត់ៗដោយអ្វីដែលក្លែងក្លាយ។"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ផ្ញើពិន្ទុការប្រកាសបណ្ដាញ"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ឲ្យកម្មវិធីប្រកាសការជូនដំណឹងដែលបណ្ដាញតម្រូវឲ្យដាក់ពិន្ទុ។ មិនចាំបាច់សម្រាប់កម្មវិធីធម្មតា។"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"កំណត់ចំនួនដំណើរការដែលកំពុងដំណើរការ"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ឲ្យកម្មវិធីពិនិត្យចំនួនដំណើរការអតិបរមាដែលនឹងដំណើរការ។ មិនចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"បង្ខំឲ្យបិទកម្មវិធីក្នុងផ្ទៃខាងក្រោយ"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតកំពូលនៃការបង្ហាញពីចម្ងាយ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចងសេវាកម្មធាតុក្រាហ្វិក"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់ទៅសេវាកម្មក្រុមហ៊ុនផ្ដល់ច្រក"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅក្រុមហ៊ុនផ្ដល់ច្រកដែលបានចុះឈ្មោះ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទងជាមួយអ្នកគ្រប់គ្រងឧបករណ៍"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យម្ចាស់ផ្ញើគោលបំណងទៅអ្នកគ្រប់គ្រងឧបករណ៍។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់ទៅការបញ្ចូលទូរទស្សន៍"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"ប្ដូរស្ថានភាព WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ឲ្យកម្មវិធីតភ្ជាប់ និងផ្ដាច់កុំព្យូទ័របន្ទះពីបណ្ដាញ WiMAX ។"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ឲ្យកម្មវិធីភ្ជាប់ទូរស័ព្ទ និងផ្ដាច់ពីបណ្ដាញ WiMAX ។"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ដាក់ពិន្ទុបណ្ដាញ"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ឲ្យកម្មវិធីចាត់ថ្នាក់បណ្ដាញ និងមានឥទ្ធិពលលើបណ្ដាញណាមួយដែលកុំព្យូទ័របន្ទះប្រើ។"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ឲ្យកម្មវិធីចាត់ថ្នាក់បណ្ដាញ និងមានឥទ្ធិពលលើបណ្ដាញណាមួយដែលទូរស័ព្ទគួរប្រើ។"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"ផ្គូផ្គងជាមួយឧបករណ៍ប៊្លូធូស"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ឲ្យកម្មវិធីមើលការកំណត់រចនាសម្ព័ន្ធប៊្លូធូសលើកុំព្យូទ័របន្ទះ ព្រមទាំងធ្វើការតភ្ជាប់ និងទទួលជាមួយឧបករណ៍បានផ្គូផ្គង។"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ឲ្យកម្មវិធីមើលការកំណត់រចនាសម្ព័ន្ធប៊្លូធូសក្នុងទូរស័ព្ទ ដើម្បីទទួល និងតភ្ជាប់ជាមួយឧបករណ៍បានផ្គូផ្គង។"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5b2747f..f73469a 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"동기화"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g> 삭제가 너무 많습니다."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"태블릿 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"시계 저장공간이 가득 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"휴대전화 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장공간을 늘리세요."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"네트워크가 모니터링될 수 있음"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"알 수 없는 제3자의 모니터링"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"벨소리가 켜져 있습니다."</string>
<string name="shutdown_progress" msgid="2281079257329981203">"종료 중..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"태블릿이 종료됩니다."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"시계가 종료됩니다."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"휴대전화가 종료됩니다."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"종료하시겠습니까?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"안전 모드로 다시 부팅"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"앱이 SMS 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 허용합니다. 이 경우 악성 앱이 수신된 SMS 메시지를 위조할 수 있습니다."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-수신 브로드캐스트 보내기"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"앱이 WAP PUSH 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 허용합니다. 이 경우 악성 앱이 MMS 메시지를 받은 것처럼 위장하거나 웹페이지의 콘텐츠를 악성 콘텐츠로 몰래 바꿀 수 있습니다."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"네트워크 점수화 브로드캐스트 전송"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"네트워크를 점수화할 필요가 있다는 알림을 앱이 브로드캐스트할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"실행 중인 프로세스 수 제한"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"앱이 실행할 최대 프로세스 수를 제어할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"백그라운드 앱 강제 종료"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"권한을 가진 프로그램이 원격 디스플레이에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"권한을 가진 프로그램이 위젯 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"경로 제공업체 서비스 사용"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"권한을 가진 프로그램이 등록된 경로 제공업체를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"기기 관리자와 상호 작용"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"권한을 가진 프로그램이 기기 관리자에게 인텐트를 보낼 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"TV 입력 사용"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX 상태 변경"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"앱이 태블릿을 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"앱이 휴대전화를 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"네트워크 점수화"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"앱이 네트워크 순위를 정하고 태블릿에서 어떤 네트워크를 선호할지 영향을 주도록 허용합니다."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"앱이 네트워크 순위를 정하고 휴대전화에서 어떤 네트워크를 선호할지 영향을 주도록 허용합니다."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"블루투스 기기와 페어링"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"앱이 태블릿의 블루투스 설정을 확인하고 페어링된 기기에 연결하며 연결을 수락할 수 있도록 허용합니다."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"앱이 휴대전화의 블루투스 설정을 확인하고 페어링된 기기에 연결하며 연결을 수락할 수 있도록 허용합니다."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index efe3354..80964b6 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ອະນຸຍາດໃຫ້ແອັບຯ ກະຈາຍສັນຍານການແຈ້ງເຕືອນວ່າຂໍ້ຄວາມ SMS ໄດ້ຮັບແລ້ວ. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດຈະໃຊ້ສິ່ງນີ້ໃນການປອມແປງຂໍ້ຄວາມ SMS ຂາເຂົ້າ."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ສົ່ງການກະຈາຍ WAP-PUSH ທີ່ໄດ້ຮັບ"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ອະນຸຍາດໃຫ້ແອັບຯສົ່ງການແຈ້ງເຕືອນໃນເວລາທີ່ໄດ້ຮັບຂໍ້ມຄວາມ WAP PUSH. ແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດໃຊ້ການກະທຳນີ້ເພື່ອປອມການໄດ້ຮັບຂໍ້ຄວາມ MMS ຫຼືລັກປ່ຽນເນື້ອຫາຂອງໜ້າເວັບຕ່າງໆ ດ້ວຍສິ່ງອັນຕະລາຍທັງຫຼາຍຢ່າງງຽບໆ."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ສົ່ງການກະຈາຍເຄືອຂ່າຍຄະແນນ"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ອະນຸຍາດໃຫ້ແອັບຯກະຈາຍການແຈ້ງເຕືອນທີ່ເຄືອຂ່າຍຈຳເປັນໃຊ້ນັບຄະແນນ. ບໍ່ເຄີຍໄດ້ໃຊ້ໃນແອັບຯທົ່ວໄປ."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ຈຳກັດຈຳນວນຂອງໂປຣເຊສທີ່ເຮັດວຽກຢູ່"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ອະນຸຍາດໃຫ້ແອັບຯຄວບຄຸມຈຳນວນສູງສຸດ ຂອງໂປຣເຊສທີ່ຈະເຮັດວຽກ. ບໍ່ຄວນຖືກໃຊ້ກັບແອັບພລິເຄຊັນທົ່ວໄປ."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"ບັງຄັບໃຫ້ແອັບຯທີ່ເຮັດວຽກຢູ່ພື້ນຫຼັງປິດໂຕລົງ"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງການສະແດງຜົນທາງໄກ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ເຊື່ອມໂຍງໄປຫາບໍລິການວິດເຈັດ"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ເຊື່ອມໂຍງກັບການບໍລິການຂອງຜູ່ໃຫ້ບໍລິການເສັ້ນທາງ"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດເຊື່ອມໂຍງກັບທຸກໆຜູ່ໃຫ້ບໍລິການເສັ້ນທາງທີ່ລົງທະບຽນ. ບໍ່ຄວນຈະໄດ້ໃຊ້ໃນແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສົ່ງເຈດຕະນາຫາຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ຜູກກັບການປ້ອນຂໍ້ມູນເຂົ້າໂທລະທັດ"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"ປ່ຽນສະຖານະ WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ແທັບເລັດຈາກເຄືອຂ່າຍ WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ຂອງໂທລະສັບຈາກເຄືອຂ່າຍ WiMax ໄດ້."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ເຄືອຂ່າຍຄະແນນ"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ອະນຸຍາດໃຫ້ແອັບຯຈັດລຳດັບເຄືອຂ່າຍ ແລະ ຊ່ວຍຕັດສິນໃຈວ່າເຄືອຂ່າຍໃດທີ່ແທັບເລັດຄວນນຳໃຊ້."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ອະນຸຍາດໃຫ້ແອັບຯຈັດລຳດັບເຄືອຂ່າຍ ແລະ ຊ່ວຍຕັດສິນໃຈວ່າເຄືອຂ່າຍໃດທີ່ໂທລະສັບຄວນນຳໃຊ້."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"ຈັບຄູ່ກັບອຸປະກອນ Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນແທັບເລັດ ຕະຫຼອດຈົນເຊື່ອມຕໍ່ ແລະຍອມຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ກັນແລ້ວ."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນໂທລະສັບ, ຮວມທັງໃຫ້ສ້າງ ແລະຮັບການເຊື່ອມຕໍ່ຈາກອຸປະກອນທີ່ຈັບຄູ່ກັນ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 2828dc2..f10135b 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinchronizuoti"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Per daug <xliff:g id="CONTENT_TYPE">%s</xliff:g> trynimo."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Planšetinio kompiuterio atmintis pilna. Kad atlaisvintumėte vietos, ištrinkite kelis failus."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Laikrodžio saugykla pilna. Ištrinkite kelis failus, kad atlaisvintumėte vietos."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefono atmintis pilna. Ištrinkite kai kuriuos failus, kad atlaisvintumėte vietos."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Tinklas gali būti stebimas"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Nežinoma trečioji šalis"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Skambutis įjungtas"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Išsijungia..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetinio kompiuterio veikimas bus sustabdytas."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Laikrodis išsijungs."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonas bus išjungtas."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Ar norite išjungti?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Iš naujo įkelti operacinę sistemą saugos režimu"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Leidžiama programai pateikti pranešimą, kad buvo gautas SMS pranešimas. Kenkėjiškos programos gali tai naudoti, kad klastotų gaunamuosius SMS pranešimus."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"siųsti „WAP-PUSH-received“ perdavimą"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Leidžiama programai pateikti pranešimą, kai gaunamas WAP PUSH pranešimas. Kenkėjiškos programos gali tai naudoti, kad klastotų MMS pranešimo gavimą ar kad nepastebimai pakeistų bet kurio tinklalapio turinį kenkėjiškais variantais."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"siųsti tinklų transliavimo įvertinimą"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Programai leidžiama transliuoti pranešimą, kad reikia įvertinti tinklus. Niekada nereikia įprastoms programoms."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"riboti vykdomų procesų skaičių"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Leidžiama programai valdyti didžiausią vykdomų procesų skaičių. Nereikalinga įprastoms programoms."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"priverstinai uždaryti fonines programas"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Leidžiama savininkui susisaistyti su aukščiausiojo lygio nuotolinio ekrano sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"susisaistyti su maršruto parinkimo paslauga"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Savininkui leidžiama susisaistyti su bet kokiomis registruotomis maršrutų parinkimo paslaugomis. To niekada neturėtų prireikti naudojant įprastas programas."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Leidžiama savininkui siųsti tikslus įrenginio administratoriui. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"susisaistyti su TV įvestimi"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Keisti „WiMAX“ būseną"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Leidžia programai prijungti planšetinį kompiuterį prie „WiMAX“ ryšio tinklų ir nuo jų atjungti."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Leidžia programai prijungti telefoną prie „WiMAX“ ryšio tinklų ir nuo jų atjungti."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"įvertinti tinklus"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Programai leidžiama įvertinti tinklus ir nustatyti, kuriems tinklams planšetiniame kompiuteryje turėtų būti taikoma pirmenybė."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Programai leidžiama įvertinti tinklus ir nustatyti, kuriems tinklams telefone turėtų būti taikoma pirmenybė."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"susieti su „Bluetooth“ įrenginiais"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją planšetiniame kompiuteryje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją telefone ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index c51cf90..f53f0ca 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizācija"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Pārāk daudz <xliff:g id="CONTENT_TYPE">%s</xliff:g> dzēsto vienumu."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Planšetdatora atmiņa ir pilna. Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Pulksteņa atmiņa ir pilna. Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Tālruņa atmiņa ir pilna! Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Iespējams, tīklā veiktās darbības tiek pārraudzītas."</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Nezināma trešā puse"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Zvanītājs ieslēgts"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Notiek izslēgšana..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetdators tiks beidzēts."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Pulkstenis tiks izslēgts."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Tālrunis tiks izslēgts."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Vai vēlaties izslēgt?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Atsāknēšana drošajā režīmā"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ļauj lietotnei pārraidīt paziņojumu par saņemtu īsziņu. Ļaunprātīgas lietotnes to var izmantot, lai viltotu ienākošas īsziņas."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"sūtīt WAP-PUSH-saņemto apraidi"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ļauj lietotnei pārraidīt paziņojumu par to, ka ir saņemts WAP PUSH ziņojums. Ļaunprātīgas lietotnes to var izmantot, lai viltotu multiziņas saņemšanu vai jebkuras tīmekļa lapas saturu nemanāmi nomainītu ar ļaunprātīgiem variantiem."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"apraidīt ziņojumu par tīklu vērtēšanu"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ļauj lietotnei apraidīt paziņojumu, ka tīkli ir jānovērtē. Parastām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ierobežot aktīvo procesu skaitu"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ļauj lietotnei kontrolēt izpildāmo procesu maksimālo skaitu. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"veikt fonā darbojošos lietotņu piespiedu aizvēršanu"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ļauj īpašniekam izveidot saiti ar attāla displeja augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Saistīšana ar maršruta nodrošinātāja pakalpojumu"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ļauj īpašniekam saistīt jebkādus reģistrētus maršrutēšanas nodrošinātājus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ļauj īpašniekam nosūtīt informāciju par nodomiem ierīces administratoram. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"Izveidot saiti ar TV ieeju"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX statusa mainīšana"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ļauj lietotnei izveidot un pārtraukt planšetdatora savienojumu ar WiMAX tīkliem."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ļauj lietotnei izveidot un pārtraukt tālruņa savienojumu ar WiMAX tīkliem."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"vērtēt tīklus"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ļauj lietotnei ranžēt tīklus un ietekmēt to, kuriem tīkliem planšetdators dos priekšroku."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ļauj lietotnei ranžēt tīklus un ietekmēt to, kuriem tīkliem tālrunis dos priekšroku."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"savienot pārī ar Bluetooth ierīcēm"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ļauj lietotnei skatīt Bluetooth konfigurāciju planšetdatorā, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ļauj lietotnei skatīt Bluetooth konfigurāciju tālrunī, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index c8c8fac..f5f8fd3 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синк"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Хэт олон <xliff:g id="CONTENT_TYPE">%s</xliff:g> устгах."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Таблетийн сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Цагны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Утасны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Сүлжээ хянагдаж байж болзошгүй"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Тодорхойгүй гуравдагч талаас"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Хонх ассан"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Унтрааж байна…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таны таблет унтрах болно."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Таны цаг унтрах болно."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Таны утас унтрах болно."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Та унтраах уу?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Аюулгүй горимоор дахин асаах"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Апп нь SMS мессеж хүлээн авсан талаарх мэдэгдлийг өргөн дамжуулах боломжтой. Хортой апп энийг ашиглан ирсэн SMS мессежийг хуурамчаар хийх боломжтой."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-хүлээн авав өргөн дамжууллыг илгээх"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Аппликешн нь WAP PUSH мессеж хүлээж авсан мэдэгдлийг өргөн дамжуулах боломжтой. Хортой апп нь энийг ашиглан MMS мессеж хүлээн авсан гэж хуурамчаар мэдэгдэх эсвэл хортой хувьсагч агуулсан веб хуудасны контентыг чимээгүй орлуулах боломжтой."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"бүртгэгдсэн сүлжээнүүд рүү түгээх"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Апп-д сүлжээнүүдэд бүртгэгдсэн байх шаардлагатай мэдэгдлийг түгээх боломжийг олгоно. Энгийн апп-д хэзээ ч шаардагдахгүй."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ажиллаж байгаа процессийн тоог хязгаарлах"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Апп нь нэг зэрэг ажиллах процессийн тооны дээд утгыг удирдах боломжтой. Энгийн апп-д хэзээ ч ашиглагдахгүй."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"арын апп-г хүчээр хаах"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Эзэмшигчид алсын дэлгэц дэх дээд давхаргын интерфэйстэй холбогдох боломж олгоно. Энгийн апп-д шаардагдахгүй."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"виджет үйлчилгээтэй холбох"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"маршрут нийлүүлэгчийн үйлчилгээтэй холбогдох"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Эзэмшигчид бүртгэгдсэн маршрут нийлүүлэгчтэй холбогдох боломж олгоно. Энгийн апп-уудад хэзээ ч шаардагдахгүй."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Эзэмшигч нь төхөөрөмжийн админруу интент илгээх боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ТВ оролт холбох"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX статусыг өөрчлөх"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Апп нь WiMAX сүлжээнд таблетыг холбох болон салгах боломжтой."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Апп нь WiMAX сүлжээнд утсыг холбох болон салгах боломжтой."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"бүртгэгдсэн сүлжээ"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Апп-д сүлжээнүүдийг эрэмбэлж, аль сүлжээнд таблетыг холбоход нөлөөлөх боломж олгоно."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Апп-д сүлжээнүүдийг эрэмбэлж, аль сүлжээнд утсыг холбоход нөлөөлөх боломж олгоно."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Блютүүт төхөөрөмжтэй хос үүсгэх"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Апп нь таблет дээрх блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Апп нь утсан дээрх Блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 0e15840..aee4cdf 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Penyegerakan"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak pemadaman <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Storan tablet penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Storan tontonan penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Storan telefon penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rangkaian mungkin dipantau"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Oleh pihak ketiga yang tidak diketahui"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Pendering dihidupkan"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Mematikan..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet anda akan dimatikan."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Tontonan anda akan dimatikan."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon anda akan dimatikan."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Adakah anda mahu menutup?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"But semula ke mod selamat"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Membenarkan apl untuk menyiarkan pemberitahuan bahawa mesej SMS telah diterima. Apl hasad boleh menggunakannya untuk memalsukan mesej SMS masuk."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"hantar siaran WAP-TOLAK-diterima"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Membenarkan apl untuk menyiarkan pemberitahuan bahawa mesej WAP PUSH telah diterima. Apl hasad boleh menggunakannya untuk memalsukan penerimaan mesej MMS atau secara diam-diam menggantikan kandungan mana-mana laman web dengan varian hasad."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"hantar siaran markah rangkaian"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Membenarkan apl menyiarkan pemberitahuan bahawa rangkaian perlu diberi markah. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"hadkan bilangan proses yang dijalankan"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Membenarkan apl untuk mengawal bilangan maksimum proses yang akan berlangsung. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"memaksa apl latar belakang untuk menutup"</string>
@@ -394,6 +390,10 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan widget. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <!-- no translation found for permlab_bindRouteProvider (4869394607915096847) -->
+ <skip />
+ <!-- no translation found for permdesc_bindRouteProvider (4703804520859960329) -->
+ <skip />
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan pentadbir peranti"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Membenarkan pemegang menghantar tujuan kepada pentadbir peranti. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ikat kepada input TV"</string>
@@ -644,12 +644,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Tukar keadaan WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Membenarkan apl untuk menyambungkan tablet ke dan menyahsambungkan tablet dari rangkaian WiMaX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Membenarkan apl untuk menyambungkan telefon ke dan menyahsambung telefon dari rangkaian WiMaX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"beri markah kepada rangkaian"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Membenarkan apl menilai rangkaian dan mempengaruhi rangkaian yang harus dipilih oleh tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Membenarkan apl menilai rangkaian dan mempengaruhi rangkaian yang harus dipilih oleh telefon."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"berpasangan dengan peranti Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Membenarkan apl melihat konfigurasi Bluetooth pada telefon dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 781f7d1..029ceb5 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkronisering"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"For mange slettinger av <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Nettbrettlageret er fullt. Slett noen filer for å frigjøre lagringsplass."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Klokkens lagringsplass er full. Slett filer for å frigjøre plass."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefonlageret er fullt. Slett noen filer for å frigjøre lagringsplass."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Nettverket blir muligens overvåket"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Av en ukjent tredjepart"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ringelyd på"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Avslutter…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Nettbrettet slås av."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Klokken slås av."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonen kommer til å slås av."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Vil du slå av?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Start på nytt i sikker modus"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Lar appen kringkaste et varsel om at en SMS-melding er mottatt. Ondsinnede apper kan bruke dette til å forfalske innkommende SMS-meldinger."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"kringkaste melding om mottatt WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Lar appen kringkaste et varsel om at en WAP-PUSH-melding er mottatt. Ondsinnede apper kan bruke dette til å forfalske MMS-meldingskvitteringer, eller ubemerket erstatte innholdet av alle slags nettsider med ondsinnede varianter."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"sende kringkasting om nettverksvurdering"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Gir appen tillatelse til å kringkaste et varsel om at nettverk må vurderes. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"begrense antallet kjørende prosesser"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lar appen kontrollere det maksimale antallet prosesser som kjører. Aldri nødvendig for vanlige apper."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge bakgrunnsapper til å lukkes"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lar innehaveren binde seg til det øverste grensesnittnivået for ekstern skjerm. Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en modultjeneste. Skal aldri være nødvendig for vanlige apper."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"binde seg til en ruteleverandørtjeneste"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Innehaveren av tillatelsen kan binde seg til ruteleverandører. Dette er ikke nødvendig for vanlige apper."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunisere med enhetsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lar innehaveren sende hensikter til en enhetsadministrator. Skal aldri være nødvendig for normale apper."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"binde applikasjonen til en TV-inngang"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Endre WiMAX-status"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverk."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lar appen koble telefonen til og fra WiMAX-nettverk."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"vurdere nettverk"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Gir appen tillatelse til å rangere nettverk, og påvirke hvilket nettverk nettbrettet skal foretrekke."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Gir appen tillatelse til å rangere nettverk, og påvirke hvilket nettverk telefonen skal foretrekke."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"koble til Bluetooth-enheter"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Lar appen se Bluetooth-konfigurasjonen på telefonen, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c45f65d..5010748 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchroniseren"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Te veel verwijderen voor <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tabletgeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Horlogegeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefoongeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netwerk kan worden gecontroleerd"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Door een onbekende derde partij"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Belsoftware aan"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Uitschakelen..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Uw tablet wordt uitgeschakeld."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Uw horloge wordt uitgeschakeld."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Uw telefoon wordt uitgeschakeld."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Wilt u afsluiten?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Opnieuw opstarten in veilige modus"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Hiermee kan de app een melding verzenden dat een sms\'je is ontvangen. Schadelijke apps kunnen dit gebruiken om inkomende sms\'jes te vervalsen."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"melding over ontvangen WAP-PUSH-bericht verzenden"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Hiermee kan de app een melding verzenden dat een WAP PUSH-bericht is ontvangen. Schadelijke apps kunnen dit gebruiken om de ontvangst van MMS-berichten te vervalsen of de inhoud van een webpagina ongemerkt te vervangen door schadelijke varianten."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"melding verzenden dat netwerken een score moeten krijgen"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Hiermee kan de app een melding uitzenden dat netwerken een score moeten krijgen. Nooit vereist voor normale apps."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"aantal actieve processen beperken"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Hiermee kan de app het maximale aantal processen beheren dat kan worden uitgevoerd. Nooit nodig voor normale apps."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"achtergrondapps gedwongen stoppen"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een extern display. Nooit vereist voor normale apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale apps."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"binden aan de service van een routeprovider"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Hiermee kan de houder binden aan geregistreerde routeproviders. Nooit gebruikt voor normale apps."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactie met apparaatbeheer"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Hiermee kan de houder intenties verzenden naar een apparaatbeheerder. Nooit vereist voor normale apps."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"binden aan een tv-ingang"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-status wijzigen"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Hiermee kan de app de telefoon verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score toekennen aan netwerken"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Hiermee kan de app netwerken rangschikken en beïnvloeden aan welke netwerken de tablet de voorkeur moet geven."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Hiermee kan de app netwerken rangschikken en beïnvloeden aan welke netwerken de telefoon de voorkeur moet geven."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"koppelen met Bluetooth-apparaten"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Hiermee kan de app de Bluetooth-configuratie van de tablet bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Hiermee kan de app de Bluetooth-configuratie van de telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3ebe3f1..c8d7298 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronizuj"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zbyt wiele usuwanych <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Pamięć tabletu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Pamięć w zegarku jest pełna. Usuń niektóre pliki, by zwolnić miejsce."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Pamięć telefonu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Sieć może być monitorowana"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Przez nieznany podmiot zewnętrzny"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Dzwonek włączony"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Wyłączanie..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet zostanie wyłączony."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Zegarek zostanie wyłączony."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon zostanie wyłączony"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Czy chcesz wyłączyć?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Uruchom w trybie awaryjnym"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Pozwala aplikacji na wysyłanie powiadomienia, że została odebrana wiadomość SMS. Złośliwe aplikacje mogą to wykorzystać do fałszowania przychodzących wiadomości SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"wysyłanie transmisji informującej o otrzymaniu wiadomości WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Pozwala aplikacji na nadanie powiadomienia o odebraniu wiadomości WAP PUSH. Złośliwe aplikacje mogą to wykorzystać do fałszowania potwierdzenia odbioru wiadomości MMS lub do niezauważalnego podmieniania zawartości dowolnej strony internetowej jej szkodliwymi wariantami."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"rozsyłanie informacji o ocenie sieci"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Pozwala aplikacji na wysłanie powiadomienia, że sieci wymagają oceny. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ograniczanie liczby uruchomionych procesów"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pozwala aplikacji na kontrolowanie maksymalnej liczby uruchamianych procesów. Nigdy niewykorzystywane przez normalne aplikacje."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"wymuszanie zamknięcia aplikacji w tle"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu wyświetlacza zdalnego. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi widżetów. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"powiązanie z usługą dostawcy tras"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umożliwia właścicielowi powiązanie z dowolnymi zarejestrowanymi dostawcami tras. Nie powinno być nigdy potrzebne w normalnych aplikacjach."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcja z administratorem urządzenia"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Zezwala na wysyłanie intencji do administratora urządzenia. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"powiązanie z wejściem TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"zmienianie stanu WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w tablecie."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w telefonie."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocenianie sieci"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Pozwala aplikacji na ocenę sieci i wybieranie sieci preferowanych przez tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Pozwala aplikacji na ocenę sieci i wybieranie sieci preferowanych przez telefon."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"parowanie z urządzeniami Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na tablecie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na telefonie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 7267cf2..718c8d9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronização"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminações de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"O armazenamento do tablet está cheio. Elimine alguns ficheiros para libertar espaço."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"O armazenamento de visualizações está cheio. Elimine alguns ficheiros para libertar espaço."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"A rede pode ser monitorizada"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por um terceiro desconhecido"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Campainha ativada"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"A encerrar..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"O seu tablet irá encerrar."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"As suas visualizações vão ser encerradas."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será encerrado."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Pretende encerrar?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que a aplicação difunda uma notificação de que foi recebida uma mensagem SMS. As aplicações maliciosas podem utilizar este recurso para forjar mensagens SMS recebidas."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar difusão recebida através de PUSH WAP"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que a aplicação difunda uma notificação de que foi recebida uma mensagens PUSH WAP. As aplicações maliciosas podem utilizar isto para forjar um recibo de mensagem MMS ou substituir, de forma silenciosa, o conteúdo de qualquer página Web por variantes maliciosas."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmissão de pontuação de redes"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite à aplicação transmitir uma notificação de que é necessário pontuar as redes. Nunca é necessário para aplicações normais."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"número limite de processos em execução"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite a uma aplicação controlar o número máximo de processos que será executado. Nunca é necessário para aplicações normais."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar as aplicações em segundo plano a fechar"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite ao detentor associar a interface de nível superior a um ecrã remoto. Nunca deve ser necessário para aplicações normais."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"vincular a serviço de fornecedor de trajeto"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite ao titular vincular a quaisquer fornecedores de trajeto registado. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite ao titular enviar intenções para um administrador do aparelho. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a uma entrada de TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que a aplicação ligue e desligue o tablet de redes WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que a aplicação ligue e desligue o telemóvel de redes WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"pontuar redes"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite à aplicação classificar redes e influenciar as redes que o tablet deve preferir."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite à aplicação classificar redes e influenciar as redes que o telemóvel deve preferir."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"sincronizar com dispositivos Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que a aplicação visualize a configuração do Bluetooth no tablet e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que a aplicação visualize a configuração do Bluetooth no telemóvel e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 690d047..29a294a7 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizar"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Muitas exclusões de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"O armazenamento do tablet está cheio. Exclua alguns arquivos para liberar espaço."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Armazenamento do relógio cheio. Exclua alguns arquivos para liberar espaço."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telefone está cheio. Exclua alguns arquivos para liberar espaço."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"A rede pode ser monitorada"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por terceiros desconhecidos"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Campainha ligada"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Encerrando…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Seu tablet será desligado."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Seu relógio será desligado."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será desligado."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Deseja desligar?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que o aplicativo transmita uma notificação quando uma mensagem SMS foi recebida. Aplicativos maliciosos podem usar esse recurso para forjar mensagens SMS recebidas."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar transmissão WAP-PUSH recebida"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que o aplicativo transmita uma notificação quando uma mensagem WAP PUSH for recebida. Aplicativos maliciosos podem usar esse recurso para forjar o recebimento de mensagens MMS ou substituir o conteúdo de qualquer página da web com variantes maliciosas."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmissão de avaliação de redes"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que o aplicativo transmita uma notificação informando que as redes devem ser avaliadas. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar número de processos em execução"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que o aplicativo controle o máximo de processos que serão executados. Nunca é necessário para aplicativos normais."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar encerramento de aplicativos em segundo plano"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite que o proprietário use a interface de nível superior de uma tela remota. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o proprietário utilize a interface de nível superior de um serviço de widget. Nunca deve ser necessário para aplicativos normais."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"usar um serviço provedor de rotas"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite que o proprietário use qualquer provedor de rotas registrado. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com o administrador de um dispositivo"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que o proprietário envie tentativas ao administrador de um aparelho. Nunca deve ser necessário para aplicativos normais."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"associar a uma entrada de TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que o aplicativo conecte e desconecte o tablet de redes WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que o aplicativo conecte e desconecte o telefone de redes WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"avaliar redes"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que o aplicativo classifique as redes e influencie a escolha de redes pelo tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que o aplicativo classifique as redes e influencie a escolha de redes pelo smartphone."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"parear com dispositivos Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que o aplicativo acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que o aplicativo acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index a9e0d4e..e362590 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -614,6 +614,10 @@
<skip />
<!-- no translation found for permdesc_bindRemoteViews (4717987810137692572) -->
<skip />
+ <!-- no translation found for permlab_bindRouteProvider (4869394607915096847) -->
+ <skip />
+ <!-- no translation found for permdesc_bindRouteProvider (4703804520859960329) -->
+ <skip />
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacziun cun in administratur dad apparats"</string>
<!-- no translation found for permdesc_bindDeviceAdmin (569715419543907930) -->
<skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index ebcf7d6..c173eef 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Spațiul de stocare de pe ceas este plin! Ștergeți câteva fișiere pentru a elibera spațiu."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rețeaua poate fi monitorizată"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"De o terță parte necunoscută"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Sonerie activată"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Se închide..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Computerul dvs. tablet PC se va închide."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ceasul dvs. se va închide."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriţi să închideţi?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniţi în modul sigur"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite aplicaţiei să difuzeze o notificare de primire a unui mesaj SMS. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a deturna primirea mesajelor SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"trimitere mesaj difuzat primit prin WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite aplicaţiei să difuzeze o notificare de primire a unui mesaj WAP PUSH. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a deturna primirea mesajelor MMS sau pentru a înlocui fără a vă înştiinţa conţinutul oricărei pagini web cu variante rău intenţionate."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"trimiteți transmisia cu rețelele punctate"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite aplicației să transmită o notificare de care rețelele au nevoie pentru a fi punctate. Nu este necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitare număr de procese în derulare"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite aplicaţiei să controleze numărul maxim de procese care vor rula. Nu este niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forţează închiderea aplicaţiilor de fundal"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite proprietarului să se conecteze la interfața de nivel superior a unui ecran la distanță. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu widget. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"se conectează la un serviciu de furnizare a traseelor"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite titularului să se conecteze la furnizorii de trasee înregistrați. Nu este necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacţionare cu administratorul unui dispozitiv"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite proprietarului să trimită intenţii către un administrator al dispozitivului. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"se conectează la o intrare TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Schimbaţi starea WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicaţiei să conecteze şi să deconecteze tableta la şi de la reţelele WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite aplicaţiei să conecteze şi să deconecteze telefonul la şi de la reţelele WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"rețele punctate"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite aplicației să clasifice rețelele și să stabilească ce rețele preferă tableta."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite aplicației să clasifice rețelele și să stabilească ce rețele preferă telefonul."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"conectează dispozitive Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite aplicaţiei să vadă configuraţia tabletei Bluetooth, să efectueze şi să accepte conexiuni cu dispozitive împerecheate."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite aplicaţiei să vadă configuraţia telefonului Bluetooth, să efectueze şi să accepte conexiuni cu dispozitive împerecheate."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 25fe679..a3d5d92 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхр."</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Слишком много удалений <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Память планшетного ПК заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Память устройства заполнена. Удалите файлы, чтобы освободить место."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Память телефона заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Сеть может отслеживаться"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"администратором"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Звонок включен"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Выключение..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Планшетный ПК будет отключен."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Устройство будет отключено."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон будет выключен."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Завершить работу?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Переход в безопасный режим"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Приложение сможет уведомлять о получении SMS. Вредоносные программы смогут таким образом подделывать входящие SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Отправка уведомлений о доставке SMS с ссылкой на WAP-страницу"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Приложение сможет уведомлять о получении сообщений WAP PUSH. Вредоносные программы смогут таким образом фальсифицировать получение MMS или незаметно подменять содержание любой страницы вредоносными данными."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"Отправка уведомлений о рейтинге сетей"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Приложение сможет отправлять уведомления о том, что сети необходимо присвоить рейтинг. Это разрешение обычно используется только специальными приложениями."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"Ограничение количества запущенных процессов"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Приложение сможет управлять максимальным количеством процессов, которые могут быть запущены. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Закрытие фоновых приложений"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Приложение сможет подключаться к базовому интерфейсу удаленного дисплея. Это разрешение обычно используется только специальными приложениями."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"Подключение к службе виджетов"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Приложение сможет подключаться к базовому интерфейсу службы виджетов. Это разрешение не используется обычными приложениями."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Подключение к серверам поставщиков маршрутов"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Приложение сможет подключаться к серверам зарегистрированных поставщиков маршрутов. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Взаимодействие с администратором устройства"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Приложение сможет отправлять объекты intent администратору устройства. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"Подключение к ТВ-входу"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Изменение статуса WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Приложение сможет подключать устройство к сетям WiMAX и отключать его от них."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Приложение сможет подключать устройство к сетям WiMAX и отключать его от них."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"Определение рейтинга сетей"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Приложение сможет присваивать сетям рейтинг и решать, к каким из них устройство должно подключаться в первую очередь."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Приложение сможет присваивать сетям рейтинг и решать, к каким из них устройство должно подключаться в первую очередь."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Установление связи с устройствами Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Приложение сможет просматривать конфигурацию Bluetooth на планшетном ПК, а также запрашивать и подтверждать соединение с другими устройствами."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Приложение сможет просматривать конфигурацию Bluetooth на телефоне, а также запрашивать и подтверждать соединение с другими устройствами."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 229e9f3..e9f3adc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronizovať"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Príliš veľa odstránených položiek služby <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Ukladací priestor tabletu je plný. Odstráňte niektoré súbory a uvoľnite miesto."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Ukladací priestor hodiniek je plný. Uvoľnite miesto odstránením niektorých súborov."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Pamäť telefónu je plná. Odstráňte niektoré súbory a uvoľnite miesto."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Sieť môže byť monitorovaná"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Neznámou treťou stranou"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Zvonenie je zapnuté"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Prebieha vypínanie..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Váš tablet bude vypnutý."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Hodinky sa vypnú."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Váš telefón bude vypnutý."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Chcete zariadenie vypnúť?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Reštartovať do núdzového režimu"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Umožňuje aplikácii vysielať oznámenie, že správa SMS bola doručená. Škodlivé aplikácie môžu toto nastavenie použiť na falšovanie prichádzajúcich správ SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"odoslanie vysielania typu WAP-PUSH-received"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Umožňuje aplikácii vysielať oznámenie, že správa WAP PUSH bola doručená. Škodlivé aplikácie môžu použiť toto nastavenie na vytvorenie potvrdenia o doručení správy MMS alebo na utajené nahradenie obsahu akejkoľvek stránky škodlivými variantmi."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"odoslanie skóre vysielaných sieťami"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Umožňuje aplikácii vysielať upozornenie, že je potrebné zadať skóre sietí. Bežné aplikácie toto povolenie nepotrebujú."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"obmedzenie počtu spustených procesov"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikácii kontrolovať maximálny počet spustených procesov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynútiť zavretie aplikácií na pozadí"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania vzdialeného displeja. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"viazanie na službu poskytovateľa cesty"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umožňuje držiteľovi viazať sa na akýchkoľvek registrovaných poskytovateľov cesty. Normálne aplikácie by toto povolenie nemali nikdy nepotrebovať."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"viazanie na televízny vstup"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Zmeniť stav siete WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikácii pripojiť tablet k sieťam WiMAX a odpojiť ho od nich."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Umožňuje aplikácii pripojiť telefón k sieťam WiMAX a odpojiť ho od nich."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"zadanie skóre sietí"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Umožňuje aplikácii hodnotiť siete a ovplyvňovať, ktoré siete by mal tablet preferovať."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Umožňuje aplikácii hodnotiť siete a ovplyvňovať, ktoré siete by mal telefón preferovať."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"párovať so zariadeniami Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index de57325..6d4f21c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizacija"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Preveč izbrisov vsebine <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Pomnilnik tabličnega računalnika je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Shramba ure je polna. Izbrišite nekaj datotek, da sprostite prostor."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Pomnilnik telefona je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Omrežje je lahko nadzorovano"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Neznana tretja oseba"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Vklopi zvonjenje"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Se zaustavlja ..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablični računalnik se bo zaustavil."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ura se bo izklopila."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon bo zaustavljen."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Ali želite izklopiti napravo?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Vnovičen zagon v varnem načinu"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Programu omogoča oddajo obvestila o prejetih sporočilih SMS. Zlonamerni programi lahko to uporabijo za ponarejanje dohodnih SMS-ov."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"pošiljanje oddaje, prejete s potisnim sporočilom WAP"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Programu omogoča oddajo obvestila, da je bilo potisno sporočilo WAP prejeto. Zlonamerni programi lahko to uporabijo za ponarejanje potrdila o prejemu sporočila MMS ali za neopazno menjavo vsebine poljubne spletne strani z zlonamernimi različicami."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"pošiljanje oddaj o ocenjevanju omrežij"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Aplikaciji dovoli oddajo obvestila, da je treba omrežja oceniti. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"omejevanje števila izvajajočih se procesov"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Programu omogoča nadzor največjega števila postopkov, ki se bodo izvajali. Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vsiljeno zapiranje aplikacij v ozadju"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Imetniku omogoča povezovanje z vmesnikom oddaljenega prikaza najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lastniku omogoča povezovanje z vmesnikom storitve pripomočka najvišje ravni. Tega ni treba nikoli uporabiti za navadne programe."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Povezava s storitvijo ponudnika poti"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Omogoča imetniku, da se povezuje z registriranimi ponudniki poti. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s skrbnikom naprave"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Omogoča lastniku, da pošlje namere skrbniku naprave. Nikoli se ne uporablja za navadne programe."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"povezava s TV-vhodom"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Sprememba stanja omrežja WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogoča, da vzpostavi povezavo med tabličnim računalnikom in omrežjem WiMAX ter jo prekine."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Aplikaciji omogoča, da vzpostavi povezavo med telefonom in omrežjem WiMAX ter jo prekine."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocenjevanje omrežij"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Aplikaciji dovoli, da omrežja razvršča in vpliva na to, katera naj tablični računalnik prednostno izbere."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Aplikaciji dovoli, da omrežja razvršča in vpliva na to, katera naj telefon prednostno izbere."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"seznanitev z napravami Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogoča ogled konfiguracije Bluetootha tabličnega računalnika ter vzpostavljanje in sprejemanje povezave s seznanjenimi napravami."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogoča ogled konfiguracije Bluetootha telefona ter ustvarjanje in sprejemanje povezave s seznanjenimi napravami."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4bf015f..1a3a235 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхронизација"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Превише <xliff:g id="CONTENT_TYPE">%s</xliff:g> избрисаних ставки."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Меморија сата је пуна. Избришите неке датотеке да бисте ослободили простор."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежа се можда надгледа"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Од стране непознате треће стране"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Звоно је укључено"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Искључивање…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблет ће се искључити."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Сат ће се угасити."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон ће се искључити."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Да ли желите да искључите телефон?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Поново покрени систем у безбедном режиму"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Дозвољава апликацији да емитује обавештење да је SMS порука примљена. Злонамерне апликације на тај начин могу да фалсификују долазне SMS поруке."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"слање примљених PUSH емитовања преко WAP-а"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозвољава апликацији да емитује обавештење да је примљена PUSH порука преко WAP-а. Злонамерне апликације то могу да искористе да фалсификују пријем MMS порука или да кришом замене садржај било које веб-странице уносом злонамерног садржаја."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"шаљи обавештења о тестирању мрежа"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Омогућава апликацији да емитује обавештење да је потребно тестирање мрежа. Никада није потребно за стандардне апликације."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"ограничење броја покренутих процеса"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозвољава апликацији да управља максималним бројем процеса који ће моћи да се покрену. Никада није потребна уобичајеним апликацијама."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудно затварање позадинских апликација"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозвољава власнику да се повеже са интерфејсом удаљеног екрана највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"повежи са услугом добављача путања"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Дозвољава власнику да се повеже са добављачима путања. Никада не би требало да буде потребно за обичне апликације."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Омогућава да власник шаље своје намере администратору уређаја. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"повезивање са ТВ улазом"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промени WiMAX статус"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозвољава апликацији да повезује таблет са WiMAX мрежама и прекида везе са њима."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Дозвољава апликацији да повезује телефон са WiMAX мрежама и прекида везе са њима."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"тестирај мреже"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Омогућава апликацији да рангира мреже и утиче на то које су мреже примарне на таблету."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Омогућава апликацији да рангира мреже и утиче на то које су мреже примарне на телефону."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"упаривање са Bluetooth уређајима"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на таблету, као и да успоставља и прихвата везе са упареним уређајима."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на телефону, као и да успоставља и прихвата везе са упареним уређајима."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 24b032e..03dc691 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkronisera"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"För många <xliff:g id="CONTENT_TYPE">%s</xliff:g>-borttagningar."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Pekdatorns lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Klockans lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Mobilens lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Nätverket kan vara övervakat"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Av en okänd tredje part"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Ringsignal på"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Avslutar…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din surfplatta stängs av."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Klockan stängs av."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon stängs av."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Vill du stänga av?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Starta om i felsäkert läge"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Tillåter att appen sänder ut en avisering när SMS tas emot. Skadliga appar kan använda detta för att förfalska inkommande SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"skicka WAP-PUSH-mottagen sändning"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Tillåter att appen skickar ett meddelande om att ett WAP PUSH-meddelande har tagits emot. Skadliga appar kan använda detta för att förfalska mottagning av MMS eller för att obemärkt byta ut innehållet på en webbsida mot skadligt innehåll."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"skicka betyg som nätverk skickar"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Tillåter att appen skickar ett meddelande om att nätverket måste betygsättas. Ska inte behövas för vanliga appar."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"begränsa antalet processer som körs"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillåter att appen styr högsta antalet processer som körs. Behövs inte för vanliga appar."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinga bakgrundsappar att avslutas"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en fjärrskärm. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind till en ruttleverantörstjänst"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Tillåter att innehavaren binds till en registrerad ruttleverantör. Detta ska inte behövas för vanliga appar."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga appar behöver aldrig göra detta."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"binda till en tv-insignal"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"ändra WiMAX-status"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillåter att appen ansluter surfplattan till eller kopplar från WiMAX-nätverk."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Tillåter att appen ansluter mobilen till eller kopplar från WiMAX-nätverk."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"betygsätt nätverk"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Tillåter att appen betygsätter nätverk och påverkar vilka nätverk som ska användas i första hand av surfplattan."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Tillåter att appen betygsätter nätverk och påverkar vilka nätverk som ska användas i första hand av mobilen."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"koppla till Bluetooth-enheter"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillåter att appen kommer åt pekdatorns Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillåter att appen kommer åt mobilens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 233bd7a..71f5003 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sawazisha"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Ufutaji mwingi sana <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Hifadhi ya kompyuta kibao imejaa. Futa baadhi ya faili ili kupata nafasi."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Hifadhi ya saa imejaa. Futa baadhi ya faili ili uweze kupata nafasi."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Hifadhi ya simu imejaa. Futa baadhi ya faili ili uweze kupata nafasi."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Huenda mtandao unafuatiliwa"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Na mtu mwingine asiyejulikana"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Programu ya milio imewashwa"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Inafunga..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Kompyuta kibao yako itazima."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Saa yako itajizima."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Simu yako itazima."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Unataka kuzima?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Washa upya kwa hali salama"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Huruhusu programu kutangaza taarifa kwamba ujumbe wa SMS umeingia. Programu hasidi zinaweza kutumia hii kubuni SMS zinazoingia."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"tuma tangazo lililopokewa la MSUKUMO WA WAP"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Inaruhusu programu kutangaza taarifa kwamba ujumbe wa WAP PUSH umepokewa. Programu hasidi zinaweza kutumia hii kubuni risiti ya ujumbe wa MMS au polepole kubadilisha maudhui yoyote ya ukurasa wa tovuti na vibadala vibovu."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"tuma tangazo la alama za mitandao"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Huruhusu programu kutangaza arifa kuwa mitandao inafaa kupewa alama. Haihitajiki kamwe kwa programu za kawaida."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"zuia idadi ya michakato inayoendeshwa"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Inaruhusu programu kudhibiti upeo wa idadi ya michakato ambayo itaendeshwa. Kamwe hazihitajiki kwa programu za kwaida."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"lazimisha programu za usuli kufunga"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Huruhusu mtumiaji kujifungia kiolesura cha kiwango cha juu cha mwonekano wa mbali. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Inaruhusu mmiliki kushurutisha kusano ya kiwango cha juu ya huduma ya wijeti. Haipaswi kuhitajika kwa programu za kawaida."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"shurutisha kwenye huduma ya mtoa huduma wa njia"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Huruhusu mmiliki kushurutisha kwenye watoa huduma wa njia waliosajiliwa. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Inamruhusu mmiliki kutuma malengo kwa msimamizi wa kifaa. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bandika kwenye zana za data ya runinga"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Badilisha hali ya WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Inaruhusu programu kuunganisha kompyuta kibao, na kukata kompyuta kibao kutoka mitandao ya WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Inaruhusu programu kuunganisha simu kwenye, na kukata simu kutoka mitandao ya WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ipe mitandao alama"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Huruhusu programu kupanga mitandao kwa alama na kushawishi mitandao ambayo kompyuta kibao inapaswa kupendelea."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Huruhusu programu kupanga mitandao kwa alama na kushawishi mitandao ambayo simu inapaswa kupendelea."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"oanisha na vifaa vya Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 452c02d..b8d99b0 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ซิงค์"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"มีการลบ <xliff:g id="CONTENT_TYPE">%s</xliff:g> มากเกินไป"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"ที่จัดเก็บข้อมูลของแท็บเล็ตเต็ม ลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ที่เก็บข้อมูลนาฬิกาเต็ม โปรดลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"ที่เก็บข้อมูลโทรศัพท์เต็ม ลบบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"เครือข่ายอาจได้รับการตรวจสอบ"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"โดยบุคคลที่สามที่ไม่รู้จัก"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"เปิดเสียง"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"กำลังปิดระบบ..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"แท็บเล็ตของคุณจะปิดการทำงาน"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"นาฬิกาจะปิดการทำงาน"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"โทรศัพท์ของคุณจะปิดเครื่อง"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"คุณต้องการปิดการทำงานหรือไม่"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"รีบูตเข้าสู่โหมดปลอดภัย"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าได้รับข้อความ SMS แล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ปลอมข้อความ SMS ที่เข้ามา"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ส่งการกระจายข้อมูลว่าได้รับ WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าได้รับข้อความ WAP PUSH แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ปลอมการแจ้งรับข้อความ MMS หรือแอบเปลี่ยนเนื้อหาในหน้าเว็บโดยใช้ตัวแปรที่เป็นอันตราย"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ส่งเผยแพร่การให้คะแนนเครือข่าย"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"อนุญาตให้แอปนี้เผยแพร่ข้อมูลการแจ้งเตือนว่าเครือข่ายจะต้องผ่านการให้คะแนน ไม่จำเป็นสำหรับแอปทั่วไป"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"จำกัดจำนวนกระบวนการที่กำลังทำงาน"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"อนุญาตให้แอปพลิเคชันควบคุมจำนวนสูงสุดของกระบวนการที่จะเรียกใช้ ไม่จำเป็นต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"บังคับปิดแอปพลิเคชันในพื้นหลัง"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"อนุญาตให้ผู้ใช้ผูกกับอินเทอร์เฟซระดับสูงสุดของจอแสดงผลระยะไกล ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการวิดเจ็ต ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"เชื่อมโยงกับบริการของผู้ให้บริการเส้นทาง"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"ช่วยให้เจ้าของสามารถเชื่อมโยงกับผู้ให้บริการเส้นทางที่ลงทะเบียนรายใดก็ได้ ไม่จำเป็นสำหรับแอปทั่วไป"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ติดต่อกับผู้ดูแลอุปกรณ์"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"อนุญาตให้ผู้ใช้ส่งการติดต่อไปยังโปรแกรมควบคุมอุปกรณ์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"เชื่อมโยงกับอินพุตทีวี"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"เปลี่ยนสถานะของ WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อแท็บเล็ตกับเครือข่าย WiMAX"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อโทรศัพท์กับเครือข่าย WiMAX"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ให้คะแนนเครือข่าย"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"อนุญาตให้แอปนี้จัดลำดับเครือข่าย ซึ่งมีผลต่อการเลือกใช้เครือข่ายของแท็บเล็ต"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"อนุญาตให้แอปนี้จัดอันดับเครือข่ายและมีผลต่อการเลือกใช้เครือข่ายของโทรศัพท์"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"จับคู่กับอุปกรณ์บลูทูธ"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของแท็บเล็ต ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของโทรศัพท์ ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index dc7de15..394f01e 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"I-sync"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Masyadong maraming pagtanggal ng <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Puno na ang storage ng tablet. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Puno na ang storage ng relo. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Puno na ang storage ng telepono. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Maaaring sinusubaybayan ang network"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ng isang di-kilalang third party"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"I-on ang ringer"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Nagsa-shut down…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Mag-shut down ang iyong tablet."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Magsa-shut down ang iyong relo."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Magsa-shut down ang iyong telepono."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Nais mo bang mag-shut down?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Mag-reboot sa safe mode"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Pinapayagan ang app na mag-broadcast ng isang notification na natanggap ang isang mensaheng SMS. Maaari itong gamitin ng nakakahamak na apps upang dayain ang papasok na mga mensaheng SMS."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ipadala ang WAP-PUSH-natanggap na pag-broadcast"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Pinapayagan ang app na mag-broadcast ng isang notification na natanggap ang isang mensaheng WAP PUSH. Maaari itong gamitin ng nakakahamak na apps upang dayain ang pagtanggap ng mensaheng MMS o upang tahimik na palitan ang nilalaman ng anumang webpage ng mga nakakahamak na variant."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"magpadala ng broadcast ng mga network ng score"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Nagbibigay-daan sa app na mag-broadcast ng notification na kailangang ma-score ng mga network. Hindi kailanman kinakailangan para sa mga normal na app."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitahan ang numero ng mga tumatakbong proseso"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pinapayagan ang app na kontrolin ang maximum na bilang ng mga proseso na tatakbo. Hindi kailanman kinakailangan para sa normal na apps."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pwersahin ang mga app sa background na magsara"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Binibigyang-daan ang may-hawak na masaklaw ang pinakamataas na antas ng interface ng isang remote na display. Hindi dapat kailanman kailanganin ng normal na apps."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng widget. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"mag-bind sa isang serbisyo ng route provider"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Nagbibigay-daan sa may-pahintulot na mag-bind sa anumang nakarehistrong route provider. Hindi dapat kailanganin kailanman ng mga normal na app."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"makipag-ugnay sa tagapangasiwa ng device"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Pinapayagan ang mga may-ari na magpadala ng mga layunin sa administrator ng device. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"i-bind sa isang TV input"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Baguhin ang katayuan ng WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pinapayagan ang app na ikonekta ang tablet at idiskonekta ang tablet mula sa mga WiMAX network."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Pinapayagan ang app na ikonekta ang telepono at idiskonekta ang telepono mula sa mga WiMAX network."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"mga network ng score"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Nagbibigay-daan sa app na iranggo ang mga network at impluwensiyahan kung aling mga network ang dapat na piliin ng tablet."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Nagbibigay-daan sa app na iranggo ang mga network at impluwensiyahan kung aling mga network ang dapat na piliin ng telepono."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"ipares sa mga Bluetooth device"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa tablet, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa telepono, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index db8c9d4..cde7219 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Senk."</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Çok fazla <xliff:g id="CONTENT_TYPE">%s</xliff:g> silme var."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Tabletin depolama alanı dolu! Yer açmak için bazı dosyaları silin."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Saat depolama alanınız dolu. Lütfen yer boşaltmak için bazı dosyaları silin."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Telefonun depolama alanı dolu! Yer açmak için bazı dosyaları silin."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Ağ izlenebilir"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Bunu, bilinmeyen üçüncü taraflar yapabilir"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Telefon zili açık"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Kapanıyor…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tabletiniz kapanacak."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Saatiniz kapatılacak."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonunuz kapanacak."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Kapatmak istiyor musunuz?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Güvenli modda yeniden aç"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Uygulamaya, SMS mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte SMS mesajları göndermek için bunu kullanabilir."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH ile alınan yayın gönder"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Uygulamaya, WAP PUSH mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte MMS bildirimleri oluşturmak veya bir web sayfasının içeriğini sessiz şekilde zararlı öğelerle değiştirmek için bunu kullanabilir."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ağları puanlama yayını gönderme"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Uygulamaya, ağların puanlanması gerektiği bildirimini yayınlama izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"çalışan işlem sayısını sınırla"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Uygulamaya, çalışacak süreçlerin azami sayısını denetleme izni verir. Normal uygulamalar için gerekli değildir."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"arka plan uygulamaları kapanmaya zorla"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"İzin sahibine, bir uzak ekranın en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cihazın sahibine bir widget hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"rota sağlayıcı hizmetine bağlanma"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"İzin verilen uygulamaya tüm kayıtlı rota sağlayıcılarına bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"bir cihaz yöneticisi ile etkileşimde bulun"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cihazın sahibinin cihaz yöneticisine amaç göndermesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"TV girişine bağlanma"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX durumunu değiştir"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Uygulamaya, tableti WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Uygulamaya, telefonu WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ağları puanlama"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Uygulamaya, ağları sıralama ve tabletin tercih edeceği ağları etkileme izni verir."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Uygulamaya, ağları sıralama ve telefonunun tercih edeceği ağları etkileme izni verir."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth cihazlarla eşle"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Uygulamaya, tabletteki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Uygulamaya, telefondaki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 388d124..f55fcf3 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -337,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Дозволяє програмі передавати сповіщення про отримання SMS повідомлення. Шкідливі програми можуть використовувати це для підробки вхідних SMS повідомлень."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"надсил. запис, отр. через WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозволяє програмі передавати сповіщення про отримання повідомлення WAP PUSH. Шкідливі програми можуть використовувати це для підробки отримання MMS повідомлень або для непомітної заміни вмісту будь-якої веб-сторінки шкідливими варіантами."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"надсилати сповіщення про оцінку мереж"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Дозволяє додатку передавати сповіщення про оцінку мереж. Ніколи не застосовується для звичайних додатків."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"обмежувати кількість запущ. процесів"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозволяє програмі контролювати максимальну кількість процесів, які буде запущено. Ніколи не вимагається для звичайних програм."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"примусово закривати фонові програми"</string>
@@ -392,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня віддаленого екрана. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"підключитися до служби постачання маршрутів"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Дозволяє власникові підключатися до зареєстрованих постачальників маршрутів. Звичайні додатки ніколи не використовують цей дозвіл."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Дозволяє власнику надсилати задавані функції адміністратору пристрою. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"підключатися до TV-входу"</string>
@@ -642,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Змінити стан WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозволяє програмі під’єднувати планшетний ПК до мереж WiMAX і від’єднувати його від них."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Дозволяє програмі під’єднувати телефон до мереж WiMAX і від’єднувати його від них."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"оцінювати мережі"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Дозволяє додатку оцінювати мережі та впливати на вибір мережі планшетом."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Дозволяє додатку оцінювати мережі та впливати на вибір мережі телефоном."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"створювати пару з пристроями Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Дозволяє програмі переглядати конфігурацію Bluetooth на планшетному ПК, а також створювати та приймати з’єднання зі спареними пристроями."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Дозволяє програмі переглядати конфігурацію Bluetooth на телефоні, а також створювати та приймати з’єднання зі спареними пристроями."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index afde154..841a68d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -339,10 +339,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Cho phép ứng dụng truyền phát thông báo cho biết đã nhận được tin nhắn SMS. Ứng dụng độc hại có thể sử dụng quyền này để giả mạo tin nhắn SMS đến."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"gửi truyền phát WAP-PUSH nhận được"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Cho phép ứng dụng truyền phát thông báo cho biết rằng đã nhận được tin nhắn WAP PUSH. Ứng dụng độc hại có thể sử dụng quyền này để giả mạo xác nhận đã nhận được tin nhắn MMS hoặc ngầm thay thế nội dung của bất kỳ trang web nào bằng các biến thể độc hại."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"gửi chương trình phát mạng điểm số"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Cho phép ứng dụng truyền thông báo rằng các mạng cần để được tính điểm. Không bao giờ cần cho ứng dụng thông thường."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"giới hạn số quá trình đang chạy"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Cho phép ứng dụng kiểm soát số quy trình tối đa sẽ chạy. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"buộc ứng dụng nền đóng"</string>
@@ -394,6 +392,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của màn hình từ xa. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tiện ích con. Không cần thiết cho các ứng dụng thông thường."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"liên kết với dịch vụ nhà cung cấp định tuyến"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Cho phép chủ sở hữu liên kết với bất kỳ nhà cung cấp định tuyến đã đăng ký nào. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"tương tác với quản trị viên thiết bị"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cho phép chủ sở hữu gửi các ý định đến quản trị viên thiết bị. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"liên kết với đầu vào TV"</string>
@@ -644,12 +644,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Thay đổi trạng thái WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Cho phép ứng dụng kết nối máy tính bảng và ngắt kết nối máy tính bảng khỏi mạng WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Cho phép ứng dụng kết nối điện thoại và ngắt kết nối điện thoại khỏi mạng WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"mạng điểm số"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Cho phép ứng dụng xếp hạng mạng và ảnh hưởng đến việc máy tính bảng nên ưu tiên mạng nào."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Cho phép ứng dụng xếp hạng các mạng và ảnh hưởng đến việc điện thoại nên ưu tiên mạng nào."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"ghép nối với thiết bị Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Cho phép ứng dụng xem cấu hình của Bluetooth trên máy tính bảng và tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại, tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
new file mode 100644
index 0000000..4c4d0ce
--- /dev/null
+++ b/core/res/res/values-watch/config.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for watch products. Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Only show power and settings items due to smaller real estate. -->
+ <string-array translatable="false" name="config_globalActionsList">
+ <item>power</item>
+ <item>settings</item>
+ </string-array>
+
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 38ce45d..020484e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同步"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"太多<xliff:g id="CONTENT_TYPE">%s</xliff:g>删除项。"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"平板电脑存储空间已满。请删除一些文件以腾出空间。"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"手表存储空间已满。请删除一些文件以腾出空间。"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"手机存储空间已满。请删除一些文件以腾出空间。"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"网络可能会受到监控"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"受到不明第三方的监控"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"振铃器开启"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"正在关机..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板电脑会关闭。"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手表即将关机。"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手机将会关机。"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"您要关机吗?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"重新启动并进入安全模式"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允许应用广播一条有关已收到短信的通知。恶意应用可能借此伪造接到的短信。"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"发送 WAP-PUSH 收到的广播"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允许应用广播一条有关已收到 WAP PUSH 短信的通知。恶意应用可能借此伪造短信接收,或在后台将任意网页的内容替换为恶意内容。"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"发送网络评分广播通知"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允许应用广播“需要为网络评分”的通知。普通应用绝不需要此权限。"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"限制运行的进程个数"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允许应用控制将运行的进程数上限。普通应用绝不需要此权限。"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"强制关闭后台应用"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允许应用绑定至远程显示屏的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到小部件服务"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许应用绑定到小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"绑定到路由程序服务"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允许应用绑定到任何已注册的路由程序。普通应用绝不需要此权限。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用绝不需要此权限。"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"绑定至电视输入设备"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 状态"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允许该应用建立和断开平板电脑与 WiMAX 网络之间的连接。"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允许该应用建立和断开手机与 WiMAX 网络之间的连接。"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"为网络评分"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允许应用为网络排名,并控制平板电脑应优先使用的网络。"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允许应用为网络排名,并控制手机应优先使用的网络。"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"与蓝牙设备配对"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允许该应用查看平板电脑上的蓝牙配置,以及建立和接受与配对设备的连接。"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允许该应用查看手机上的蓝牙配置,以及建立和接受与配对设备的连接。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index e4f54af..8841536 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Google Sync"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"平板電腦的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"手錶的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"手機的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"網絡可能會受到監控"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"由不明的第三方監管"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"鈴聲開啟"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"正在關機..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板電腦將會關機。"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手錶即將關機。"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手機即將關機。"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"您要關機嗎?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"重新啟動進入安全模式"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允許應用程式在收到短訊時發出通知。惡意應用程式可能會藉此偽造外來短訊。"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"傳送可由 WAP PUSH 接收的廣播"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允許應用程式在收到 WAP PUSH 訊息時發送通知。惡意應用程式可能會藉此偽造 MMS 訊息回條或私自以惡意內容更換網頁。"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"傳送網絡計分廣播"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允許應用程式廣播網絡需要計分的通知,但一般應用程式並不需要使用。"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"執行程序數目上限"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允許應用程式控制可執行程序的數量上限 (不建議一般應用程式使用)。"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"強制關閉背景應用程式"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端屏螢的頂層介面 (不建議一般應用程式使用)。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"繫結至路由供應商服務"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允許應用程式繫結至任何已註冊的路由供應商,但一般應用程式並不需要使用。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (不建議一般應用程式使用)。"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 狀態"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允許應用程式建立或中斷平板電腦與 WiMAX 網絡的連線。"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允許應用程式建立或中斷手機與 WiMAX 網絡的連線。"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"為網絡計分"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允許應用程式為網絡排名,及決定平板電腦偏好使用的網絡。"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允許應用程式為網絡排名,及決定手機偏好使用的網絡。"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"與藍牙裝置配對"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9b89c75..bab94b4 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同步處理"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"平板電腦的儲存空間已滿。請刪除一些檔案,以釋放出可用空間。"</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"手錶儲存空間已用盡,請刪除一些檔案以釋出可用空間。"</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"手機儲存空間已滿。請刪除一些檔案,以釋放可用空間。"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"網路可能會受到監控"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"受到不明的第三方監控"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"鈴聲開啟"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"關機中…"</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板電腦將會關機。"</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手錶即將關機。"</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"手機即將關機。"</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"您要關機嗎?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"重新啟動進入安全模式"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允許應用程式在收到 SMS 簡訊時發出通知。請注意,惡意應用程式可能利用此功能偽造外來的 SMS 簡訊。"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"送出「WAP PUSH 已接收」廣播"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允許應用程式在收到 WAP PUSH 訊息時發送通知。請注意,惡意應用程式可能利用此功能偽造 MMS 簡訊回條,或私自將網頁內容更換為惡意陷阱。"</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"傳送網路計分廣播通知"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允許應用程式廣播網路需計分的通知訊息 (一般應用程式並不需要)。"</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"執行程序限制數"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允許應用程式控制可執行程序的數量上限 (一般應用程式不需使用)。"</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"強制關閉背景應用程式"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端螢幕的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (一般應用程式不需使用)。"</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"繫結至路由供應商服務"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允許應用程式繫結至任何已註冊的路由供應商 (一般應用程式並不需要)。"</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (一般應用程式不需使用)。"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"變更 WiMAX 狀態"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允許應用程式建立或中斷平板電腦與 WiMAX 網路的連線。"</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允許應用程式建立或中斷手機與 WiMAX 網路的連線。"</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"為網路計分"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允許應用程式建立網路排名,決定平板電腦偏好使用的網路。"</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允許應用程式建立網路排名,決定手機偏好使用的網路。"</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"與藍牙裝置配對"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e552c4e..4dbd003 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -135,8 +135,7 @@
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Vumelanisa"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Kunokususa <xliff:g id="CONTENT_TYPE">%s</xliff:g> okuningi kakhulu."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
- <!-- no translation found for low_memory (4415914910770005166) -->
- <skip />
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"Isitoreji sokubuka sigcwele. Susa amanye amafayela ukukhulula isikhala."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Isilondolozi sefoni sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Inethiwekhi ingase inganyelwe"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ngenkampani yangaphandle engaziwa"</string>
@@ -154,8 +153,7 @@
<string name="silent_mode_ring" msgid="8592241816194074353">"Iringa iyasebenza"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Ivala shaqa..."</string>
<string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ithebhulethi yakho izocima."</string>
- <!-- no translation found for shutdown_confirm (3490275567476369184) -->
- <skip />
+ <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ukubuka kwakho kuzocima."</string>
<string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ifoni yakho izocima."</string>
<string name="shutdown_confirm_question" msgid="2906544768881136183">"Ingabe ufuna ukucisha?"</string>
<string name="reboot_safemode_title" msgid="7054509914500140361">"Qala kabusha emodini ephephile"</string>
@@ -339,10 +337,8 @@
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ivumela uhlelo lokusebenza ukuthi isakaze isaziso sokuthi umyalezo we-SMS utholakele. Izuhlelo lokusebenza ezinobungozi zingasebenzisa lokhu ukufoja imiyalezo ye-SMS engenayo."</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"thumela umsakazo otholwe nge-WAP-PUSH"</string>
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ivumela uhlelo lokusebenza ukuthi isakaze isaziso sokuthi umyalezo we-WAP PUSH utholakele. Izuhlelo lokusebenza ezinobungozi zingasebenzisa lokhu ukufoja ukutholakala kwemiyalezo ye-S noma zisuse okuqukethwe kwanoma iliphi ikhasi lewebhu eliqukethe okunobungozi."</string>
- <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
- <skip />
- <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
- <skip />
+ <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"thumela ukusakaza kwamanethiwekhi ayisikolo"</string>
+ <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ivumela uhlelo lokusebenza ukusakaza isaziso sokuthi amanethiwekhi adinga isikolo. Awadingeki kuzinhlelo zokusebenza ezivamile."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"khawula inani lezinqubo ezisebenzayo"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ivumela uhlelo lokusebenza ukuthi ilawule isibalo esikhulu sezinto eziqhubekayo eziyosebenza. Ayidingakeli izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_setAlwaysFinish" msgid="550958507798796965">"phoqa izinhlelo zokusebenza ezingemuva ukuthi zivaleke"</string>
@@ -394,6 +390,8 @@
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo esisezingeni eliphezulu sesibonisi sesilawuli kude. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bophezela kube isevisi yesinqunjana"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
+ <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bophezela kusevisi yomhlinzeki womzila"</string>
+ <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ivumela isibambi ukubophezela kunoma yimuphi umhlinzeki womzila obhalisiwe. Akufanele kudingeke izinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ivumela ummeli ukuthumela okuqukethwe kumphathi wedivaysi. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bophezela kokokufaka kwe-TV"</string>
@@ -644,12 +642,9 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Shintsha isimo se-WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ivumela uhlelo lokusebenza ukuxhuma ithebhulethi nokunqamula ithebhulethi kumanethiwekhi e-WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ivumela uhlelo lokusebenza ukuxhuma ifoni nokuyinqamula kumanethiwekhi e-WiMAX."</string>
- <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
- <skip />
- <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
- <skip />
+ <string name="permlab_scoreNetworks" msgid="6445777779383587181">"amanethiwekhi ayisikolo"</string>
+ <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ivumela uhlelo lokusebenza ukuthi lilinganise amanethiwekhi futhi lithuthukise ukuthi imaphi amanethiwekhi ithebhulethi okufanele iwakhethe."</string>
+ <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ivumela uhlelo lokusebenza ukuthi lilinganise amanethiwekhi futhi lithuthukise ukuthi imaphi amanethiwekhi ifoni okufanele iwakhethe."</string>
<string name="permlab_bluetooth" msgid="6127769336339276828">"matanisa namadivayisi e-Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kuthebhulethi, nokwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth efonini, ukwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 782066e..b7bffde 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4504,6 +4504,8 @@
result to valid color values. Saturate(S + D) -->
<enum name="add" value="16" />
</attr>
+ <!-- Specifies the alpha multiplier to apply to the base drawable. -->
+ <attr name="alpha" />
</declare-styleable>
<!-- Drawable used to draw 9-patches. -->
@@ -4523,6 +4525,8 @@
<!-- When a tint color is set, specifies its Porter-Duff blending mode. The
default value is src_in, which treats the drawable as an alpha mask. -->
<attr name="tintMode" />
+ <!-- Specifies the alpha multiplier to apply to the base drawable. -->
+ <attr name="alpha" />
</declare-styleable>
<!-- Drawable used to draw a single color. -->
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index ebe4a49..f8f192f 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -118,11 +118,11 @@
<!-- Text & foreground colors -->
- <color name="primary_text_quantum_light">#de000000</color>
+ <color name="primary_text_default_quantum_light">#de000000</color>
<color name="secondary_text_quantum_light">#8a000000</color>
<color name="tertiary_text_quantum_light">#4d000000</color>
- <color name="primary_text_quantum_dark">#deffffff</color>
+ <color name="primary_text_default_quantum_dark">#deffffff</color>
<color name="secondary_text_quantum_dark">#8affffff</color>
<color name="tertiary_text_quantum_dark">#4dffffff</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2df5dc1..f919c9f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -807,6 +807,21 @@
<item>com.android.location.fused</item>
</string-array>
+ <!-- This string array can be overriden to enable test location providers initially. -->
+ <!-- Array of "[locationProviderName],[requiresNetwork],
+ [requiresSatellite],[requiresCell],[hasMonetaryCost],
+ [supportAltitute],[supportsSpeed],[supportsBearing],
+ [powerRequirement],[accuracy]" -->
+ <!-- powerRequirement is defined in android.location.Criteria
+ 0 = NO_REQUIREMENT / 1 = POWER_LOW / 2 = POWER_MEDIUM / 3 = POWER_HIGH -->
+ <!-- accuracy is defined in anroid.location.Criteria
+ 1 = ACCURACY_FINE / 2 = ACCURACY_COARSE -->
+ <string-array name="config_testLocationProviders" translatable="false">
+ <!-- Example test network location provider
+ <item>network,false,false,false,false,true,true,true,1,2</item>
+ -->
+ </string-array>
+
<!-- Boolean indicating if current platform supports bluetooth SCO for off call
use cases -->
<bool name="config_bluetooth_sco_off_call">true</bool>
@@ -1432,4 +1447,25 @@
<!-- default window inset isRound property -->
<bool name="config_windowIsRound">false</bool>
+ <!-- Package name for default network scorer app; overridden by product overlays. -->
+ <string name="config_defaultNetworkScorerPackageName"></string>
+
+ <!-- Defines the default set of global actions. Actions may still be disabled or hidden based
+ on the current state of the device.
+ Each item must be one of the following strings:
+ "power" = Power off
+ "settings" = An action to launch settings
+ "airplane" = Airplane mode toggle
+ "bugreport" = Take bug report, if available
+ "silent" = silent mode
+ "users" = list of users
+ -->
+ <string-array translatable="false" name="config_globalActionsList">
+ <item>power</item>
+ <item>airplane</item>
+ <item>bugreport</item>
+ <item>silent</item>
+ <item>users</item>
+ </string-array>
+
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index cacb41f..6d4ceef 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -399,6 +399,9 @@
<!-- status message in phone options dialog for when airplane mode is off -->
<string name="global_actions_airplane_mode_off_status">Airplane mode is OFF</string>
+ <!-- label for item that launches settings in phone options dialog [CHAR LIMIT=15]-->
+ <string name="global_action_settings">Settings</string>
+
<!-- Text to use when the number in a notification info is too large
(greater than status_bar_notification_info_maxnum, defined in
values/config.xml) and must be truncated. May need to be localized
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index bdc7ad0..0cbb655 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -485,11 +485,18 @@
</style>
<style name="Widget.Quantum.CompoundButton" parent="Widget.CompoundButton"/>
- <style name="Widget.Quantum.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox"/>
- <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton"/>
+
+ <style name="Widget.Quantum.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox">
+ <item name="background">?attr/selectableItemBackground</item>
+ </style>
+
+ <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton">
+ <item name="background">?attr/selectableItemBackground</item>
+ </style>
<style name="Widget.Quantum.CompoundButton.Star" parent="Widget.CompoundButton.Star">
<item name="button">@drawable/btn_star_quantum</item>
+ <item name="background">?attr/selectableItemBackground</item>
</style>
<style name="Widget.Quantum.CompoundButton.Switch">
@@ -501,6 +508,7 @@
<item name="thumbTextPadding">12dip</item>
<item name="switchMinWidth">72dip</item>
<item name="switchPadding">16dip</item>
+ <item name="background">?attr/selectableItemBackground</item>
</style>
<style name="Widget.Quantum.EditText" parent="Widget.EditText"/>
@@ -619,6 +627,7 @@
<item name="paddingStart">16dip</item>
<item name="paddingEnd">16dip</item>
<item name="mirrorForRtl">true</item>
+ <item name="background">?attr/selectableItemBackground</item>
</style>
<style name="Widget.Quantum.RatingBar" parent="Widget.RatingBar">
@@ -846,7 +855,15 @@
<item name="popupBackground">?attr/colorBackground</item>
</style>
+ <style name="Widget.Quantum.Light.CompoundButton" parent="Widget.Quantum.CompoundButton"/>
<style name="Widget.Quantum.Light.CompoundButton.CheckBox" parent="Widget.Quantum.CompoundButton.CheckBox"/>
+ <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
+ <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
+
+ <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
+ <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
+ </style>
+
<style name="Widget.Quantum.Light.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
<style name="Widget.Quantum.Light.EditText" parent="Widget.Quantum.EditText"/>
<style name="Widget.Quantum.Light.ExpandableListView" parent="Widget.Quantum.ExpandableListView"/>
@@ -916,7 +933,6 @@
<item name="maxHeight">16dip</item>
</style>
- <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
<style name="Widget.Quantum.Light.ScrollView" parent="Widget.Quantum.ScrollView"/>
<style name="Widget.Quantum.Light.HorizontalScrollView" parent="Widget.Quantum.HorizontalScrollView"/>
@@ -932,7 +948,6 @@
<style name="Widget.Quantum.Light.Spinner.DropDown" parent="Widget.Quantum.Spinner.DropDown"/>
<style name="Widget.Quantum.Light.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Spinner.DropDown.ActionBar"/>
- <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
<style name="Widget.Quantum.Light.TabWidget" parent="Widget.Quantum.TabWidget"/>
<style name="Widget.Quantum.Light.WebTextView" parent="Widget.Quantum.WebTextView"/>
<style name="Widget.Quantum.Light.WebView" parent="Widget.Quantum.WebView"/>
@@ -989,10 +1004,6 @@
<item name="backgroundSplit">?attr/colorPrimary</item>
</style>
- <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
- <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
- </style>
-
<style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
<style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 03c617a..bc92107 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -987,6 +987,7 @@
<java-symbol type="array" name="config_operatorConsideredNonRoaming" />
<java-symbol type="array" name="config_sameNamedOperatorConsideredRoaming" />
<java-symbol type="array" name="config_callBarringMMI" />
+ <java-symbol type="array" name="config_globalActionsList" />
<java-symbol type="drawable" name="default_wallpaper" />
<java-symbol type="drawable" name="indicator_input_error" />
@@ -1230,6 +1231,7 @@
<java-symbol type="xml" name="sms_short_codes" />
<java-symbol type="xml" name="audio_assets" />
<java-symbol type="xml" name="global_keys" />
+ <java-symbol type="xml" name="default_zen_mode_config" />
<java-symbol type="raw" name="accessibility_gestures" />
<java-symbol type="raw" name="incognito_mode_start_page" />
@@ -1388,6 +1390,7 @@
<java-symbol type="string" name="global_actions_airplane_mode_on_status" />
<java-symbol type="string" name="global_actions_toggle_airplane_mode" />
<java-symbol type="string" name="global_action_bug_report" />
+ <java-symbol type="string" name="global_action_settings" />
<java-symbol type="string" name="global_action_silent_mode_off_status" />
<java-symbol type="string" name="global_action_silent_mode_on_status" />
<java-symbol type="string" name="global_action_toggle_silent_mode" />
@@ -1441,6 +1444,7 @@
<java-symbol type="array" name="radioAttributes" />
<java-symbol type="array" name="config_oemUsbModeOverride" />
<java-symbol type="array" name="config_locationProviderPackageNames" />
+ <java-symbol type="array" name="config_testLocationProviders" />
<java-symbol type="array" name="config_defaultNotificationVibePattern" />
<java-symbol type="array" name="config_notificationFallbackVibePattern" />
<java-symbol type="array" name="config_onlySingleDcAllowed" />
@@ -1460,6 +1464,7 @@
<java-symbol type="color" name="input_method_navigation_guard" />
<java-symbol type="drawable" name="ic_notification_ime_default" />
<java-symbol type="drawable" name="ic_menu_refresh" />
+ <java-symbol type="drawable" name="ic_settings" />
<java-symbol type="drawable" name="stat_notify_car_mode" />
<java-symbol type="drawable" name="stat_notify_disabled" />
<java-symbol type="drawable" name="stat_notify_disk_full" />
@@ -1625,6 +1630,7 @@
<java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
<java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
<java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
+ <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
new file mode 100644
index 0000000..1bdc1ec
--- /dev/null
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, 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.
+*/
+-->
+
+<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
+<zen version="1">
+ <allow calls="false" messages="false" />
+ <sleep startHour="22" startMin="0" endHour="7" endMin="0" />
+</zen>
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
index 60b6dc1..cbfa84d 100644
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ b/core/tests/bluetoothtests/AndroidManifest.xml
@@ -31,5 +31,8 @@
<instrumentation android:name="android.bluetooth.BluetoothTestRunner"
android:targetPackage="com.android.bluetooth.tests"
android:label="Bluetooth Tests" />
+ <instrumentation android:name="android.bluetooth.BluetoothInstrumentation"
+ android:targetPackage="com.android.bluetooth.tests"
+ android:label="Bluetooth Test Utils" />
</manifest>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
new file mode 100644
index 0000000..34393f9
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 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.bluetooth;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Bundle;
+
+public class BluetoothInstrumentation extends Instrumentation {
+
+ private BluetoothTestUtils mUtils = null;
+ private BluetoothAdapter mAdapter = null;
+ private Bundle mArgs = null;
+
+ private BluetoothTestUtils getBluetoothTestUtils() {
+ if (mUtils == null) {
+ mUtils = new BluetoothTestUtils(getContext(),
+ BluetoothInstrumentation.class.getSimpleName());
+ }
+ return mUtils;
+ }
+
+ private BluetoothAdapter getBluetoothAdapter() {
+ if (mAdapter == null) {
+ mAdapter = ((BluetoothManager)getContext().getSystemService(
+ Context.BLUETOOTH_SERVICE)).getAdapter();
+ }
+ return mAdapter;
+ }
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ super.onCreate(arguments);
+ mArgs = arguments;
+ start();
+ }
+
+ @Override
+ public void onStart() {
+ String command = mArgs.getString("command");
+ if ("enable".equals(command)) {
+ enable();
+ } else if ("disable".equals(command)) {
+ disable();
+ } else if ("unpairAll".equals(command)) {
+ unpairAll();
+ } else if ("getName".equals(command)) {
+ getName();
+ } else {
+ finish(null);
+ }
+ }
+
+ public void enable() {
+ getBluetoothTestUtils().enable(getBluetoothAdapter());
+ finish(null);
+ }
+
+ public void disable() {
+ getBluetoothTestUtils().disable(getBluetoothAdapter());
+ finish(null);
+ }
+
+ public void unpairAll() {
+ getBluetoothTestUtils().unpairAll(getBluetoothAdapter());
+ finish(null);
+ }
+
+ public void getName() {
+ String name = getBluetoothAdapter().getName();
+ Bundle bundle = new Bundle();
+ bundle.putString("name", name);
+ finish(bundle);
+ }
+
+ public void finish(Bundle result) {
+ if (result == null) {
+ result = new Bundle();
+ }
+ finish(Activity.RESULT_OK, result);
+ }
+}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index 4858be8..8fbd214 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -34,6 +34,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
public class BluetoothTestUtils extends Assert {
@@ -893,6 +894,17 @@
}
/**
+ * Deletes all pairings of remote devices
+ * @param adapter the BT adapter
+ */
+ public void unpairAll(BluetoothAdapter adapter) {
+ Set<BluetoothDevice> devices = adapter.getBondedDevices();
+ for (BluetoothDevice device : devices) {
+ unpair(adapter, device);
+ }
+ }
+
+ /**
* Connects a profile from the local device to a remote device and checks to make sure that the
* profile is connected and that the correct actions were broadcast.
*
diff --git a/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
similarity index 95%
rename from core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java
rename to core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 6d5ede8..cac6b93 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -33,7 +33,7 @@
import java.util.Iterator;
-public class NetworkScorerApplicationTest extends InstrumentationTestCase {
+public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
@Mock private Context mMockContext;
@Mock private PackageManager mMockPm;
@@ -64,7 +64,7 @@
setScorers(package1, package2, package3);
Iterator<String> result =
- NetworkScorerApplication.getAllValidScorers(mMockContext).iterator();
+ NetworkScorerAppManager.getAllValidScorers(mMockContext).iterator();
assertTrue(result.hasNext());
assertEquals("package1", result.next());
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index 6fb8946..cd45017 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -19,12 +19,14 @@
import android.content.ContentUris;
import android.os.Parcel;
import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import junit.framework.TestCase;
public class UriTest extends TestCase {
@@ -752,4 +754,54 @@
assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c"));
assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c"));
}
+
+ public void testPathPrefixMatch() {
+ // Exact match
+ assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+ assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+ Uri.parse("content://com.example/path")));
+ assertTrue(Uri.parse("content://com.example///path///").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+ assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+ Uri.parse("content://com.example///path///")));
+
+ // Child match
+ assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+ assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
+ Uri.parse("content://com.example/path")));
+
+ // Extra parameters
+ assertTrue(Uri.parse("content://com.example/path#fragment").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+ assertTrue(Uri.parse("content://com.example/path?q=v").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+ assertTrue(Uri.parse("content://com.example/path/?q=v").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/")));
+
+ // Different path
+ assertFalse(Uri.parse("content://com.example/path").isPathPrefixMatch(
+ Uri.parse("content://com.example/path/deeper/")));
+ assertFalse(Uri.parse("content://com.example/path2").isPathPrefixMatch(
+ Uri.parse("content://com.example/path")));
+
+ // Top-level match
+ assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+ Uri.parse("content://com.example/")));
+ assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+ Uri.parse("content://com.example")));
+
+ // Different prefixes
+ assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+ Uri.parse("file://com.example/path/")));
+ assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+ Uri.parse("content://org.example/path/")));
+
+ // Escaping
+ assertTrue(Uri.parse("content://com.example/path path/").isPathPrefixMatch(
+ Uri.parse("content://com.example/path%20path/")));
+ assertFalse(Uri.parse("content://com.example/path/path").isPathPrefixMatch(
+ Uri.parse("content://com.example/path%2Fpath")));
+ }
}
diff --git a/data/keyboards/Vendor_1949_Product_0401.kl b/data/keyboards/Vendor_1949_Product_0401.kl
new file mode 100644
index 0000000..ab24bcd
--- /dev/null
+++ b/data/keyboards/Vendor_1949_Product_0401.kl
@@ -0,0 +1,27 @@
+# Copyright (C) 2014 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.
+
+# Amazon Fire TV remote
+
+key 103 DPAD_UP
+key 108 DPAD_DOWN
+key 105 DPAD_LEFT
+key 106 DPAD_RIGHT
+key 96 DPAD_CENTER
+key 158 BACK
+key 172 HOME
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
+key 164 MEDIA_PLAY_PAUSE
+key 217 ASSIST
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index a122443..a61696a 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -1126,8 +1126,8 @@
uses a string array as the data source:</p>
<pre>
-SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
- android.R.layout.simple_spinner_dropdown_item);
+SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
+ R.array.action_list, android.R.layout.simple_spinner_dropdown_item);
</pre>
<p>The {@link android.widget.ArrayAdapter#createFromResource createFromResource()} method takes
@@ -1145,7 +1145,7 @@
<item>Venus</item>
<item>Earth</item>
</string-array>
-</pre>
+</resources>
</pre>
<p>The {@link android.widget.ArrayAdapter} returned by {@link
@@ -1179,10 +1179,13 @@
public boolean onNavigationItemSelected(int position, long itemId) {
// Create new fragment from our own Fragment class
ListContentFragment newFragment = new ListContentFragment();
- FragmentTransaction ft = openFragmentTransaction();
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+
// Replace whatever is in the fragment container with this fragment
- // and give the fragment a tag name equal to the string at the position selected
+ // and give the fragment a tag name equal to the string at the position
+ // selected
ft.replace(R.id.fragment_container, newFragment, strings[position]);
+
// Apply changes
ft.commit();
return true;
@@ -1210,7 +1213,8 @@
@Override
public void onAttach(Activity activity) {
// This is the first callback received; here we can set the text for
- // the fragment as defined by the tag specified during the fragment transaction
+ // the fragment as defined by the tag specified during the fragment
+ // transaction
super.onAttach(activity);
mText = getTag();
}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 66a88a2..60b4615 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -484,6 +484,15 @@
copyBounds(mDstRect);
}
+ final int restoreAlpha;
+ if (state.mBaseAlpha != 1.0f) {
+ final Paint p = getPaint();
+ restoreAlpha = p.getAlpha();
+ p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
+ } else {
+ restoreAlpha = -1;
+ }
+
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
@@ -537,6 +546,10 @@
if (clearColorFilter) {
paint.setColorFilter(null);
}
+
+ if (restoreAlpha >= 0) {
+ paint.setAlpha(restoreAlpha);
+ }
}
@Override
@@ -762,6 +775,10 @@
paint.setDither(dither);
}
+ if (themeAttrs == null || themeAttrs[R.styleable.BitmapDrawable_alpha] == 0) {
+ state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, 1.0f);
+ }
+
if (themeAttrs == null || themeAttrs[R.styleable.BitmapDrawable_gravity] == 0) {
final int gravity = a.getInt(
R.styleable.BitmapDrawable_gravity, Gravity.FILL);
@@ -818,6 +835,10 @@
paint.setDither(dither);
}
+ if (a.hasValue(R.styleable.BitmapDrawable_alpha)) {
+ state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, state.mBaseAlpha);
+ }
+
if (a.hasValue(R.styleable.BitmapDrawable_gravity)) {
final int gravity = a.getInt(
R.styleable.BitmapDrawable_gravity, Gravity.FILL);
@@ -933,6 +954,7 @@
int[] mThemeAttrs;
int mChangingConfigurations;
int mGravity = Gravity.FILL;
+ float mBaseAlpha = 1.0f;
Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
Shader.TileMode mTileModeX = null;
Shader.TileMode mTileModeY = null;
@@ -954,6 +976,7 @@
mTileModeX = bitmapState.mTileModeX;
mTileModeY = bitmapState.mTileModeY;
mTargetDensity = bitmapState.mTargetDensity;
+ mBaseAlpha = bitmapState.mBaseAlpha;
mPaint = new Paint(bitmapState.mPaint);
mRebuildShader = bitmapState.mRebuildShader;
mAutoMirrored = bitmapState.mAutoMirrored;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 21cd5db..74d1219 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -518,9 +518,16 @@
public void removeHotspot(int key) {}
/**
- * Removes all hotspots from the drawable.
+ * Immediately removes all hotspots from the drawable.
*/
public void clearHotspots() {}
+
+ /**
+ * Sets the bounds to which hotspots are constrained.
+ *
+ * @hide until we finalize these APIs
+ */
+ public void setHotspotBounds(int left, int top, int right, int bottom) {}
/**
* Whether this drawable requests projection.
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 05df3bc..1f8b51d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -238,6 +238,35 @@
}
@Override
+ public void setHotspot(int key, float x, float y) {
+ if (mCurrDrawable != null) {
+ mCurrDrawable.setHotspot(key, x, y);
+ }
+ }
+
+ @Override
+ public void removeHotspot(int key) {
+ if (mCurrDrawable != null) {
+ mCurrDrawable.removeHotspot(key);
+ }
+ }
+
+ @Override
+ public void clearHotspots() {
+ if (mCurrDrawable != null) {
+ mCurrDrawable.clearHotspots();
+ }
+ }
+
+ @Override
+ public boolean supportsHotspots() {
+ if (mCurrDrawable != null) {
+ return mCurrDrawable.supportsHotspots();
+ }
+ return false;
+ }
+
+ @Override
protected boolean onStateChange(int[] state) {
if (mLastDrawable != null) {
return mLastDrawable.setState(state);
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index b366987..639d719 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -290,6 +290,26 @@
return false;
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean isProjected() {
+ if (super.isProjected()) {
+ return true;
+ }
+
+ final ChildDrawable[] layers = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i = 0; i < N; i++) {
+ if (layers[i].mDrawable.isProjected()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
/**
* Add a new layer to this drawable. The new layer is identified by an id.
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 3e9ca0a..21992ce 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -241,6 +241,15 @@
canvas.scale(-1.0f, 1.0f);
}
+ final int restoreAlpha;
+ if (mNinePatchState.mBaseAlpha != 1.0f) {
+ final Paint p = getPaint();
+ restoreAlpha = p.getAlpha();
+ p.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
+ } else {
+ restoreAlpha = -1;
+ }
+
mNinePatch.draw(canvas, bounds, mPaint);
if (needsMirroring) {
@@ -250,6 +259,10 @@
if (clearColorFilter) {
mPaint.setColorFilter(null);
}
+
+ if (restoreAlpha >= 0) {
+ mPaint.setAlpha(restoreAlpha);
+ }
}
@Override
@@ -491,6 +504,10 @@
}
}
+ if (themeAttrs == null || themeAttrs[R.styleable.NinePatchDrawable_alpha] == 0) {
+ ninePatchState.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, 1.0f);
+ }
+
// Apply the constant state to the paint.
initializeWithState(ninePatchState, r);
@@ -584,6 +601,10 @@
}
}
+ if (a.hasValue(R.styleable.NinePatchDrawable_alpha)) {
+ state.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, 1.0f);
+ }
+
// Apply the constant state to the paint.
initializeWithState(state, r);
@@ -689,12 +710,13 @@
Mode mTintMode = Mode.SRC_IN;
Rect mPadding;
Insets mOpticalInsets;
+ float mBaseAlpha = 1.0f;
boolean mDither;
int[] mThemeAttrs;
int mChangingConfigurations;
int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
boolean mAutoMirrored;
-
+
NinePatchState() {
// Empty constructor.
}
@@ -726,6 +748,7 @@
mThemeAttrs = state.mThemeAttrs;
mPadding = state.mPadding;
mOpticalInsets = state.mOpticalInsets;
+ mBaseAlpha = state.mBaseAlpha;
mDither = state.mDither;
mChangingConfigurations = state.mChangingConfigurations;
mTargetDensity = state.mTargetDensity;
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 03dd841..e3f57e9 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -62,27 +62,31 @@
/** Whether the center is within the parent bounds. */
private boolean mInside;
+
+ /** Whether to pulse this ripple. */
+ boolean mPulse;
/** Enter state. A value in [0...1] or -1 if not set. */
- private float mEnterState = -1;
+ float mEnterState = -1;
/** Exit state. A value in [0...1] or -1 if not set. */
- private float mExitState = -1;
+ float mExitState = -1;
/** Outside state. A value in [0...1] or -1 if not set. */
- private float mOutsideState = -1;
+ float mOutsideState = -1;
/** Pulse state. A value in [0...1] or -1 if not set. */
- private float mPulseState = -1;
+ float mPulseState = -1;
/**
* Creates a new ripple with the specified parent bounds, padding, initial
* position, and screen density.
*/
- public Ripple(Rect bounds, Rect padding, float x, float y, float density) {
+ public Ripple(Rect bounds, Rect padding, float x, float y, float density, boolean pulse) {
mBounds = bounds;
mPadding = padding;
mInside = mBounds.contains((int) x, (int) y);
+ mPulse = pulse;
mX = x;
mY = y;
@@ -115,6 +119,16 @@
}
}
+ public void onBoundsChanged() {
+ final boolean inside = mBounds.contains((int) mX, (int) mY);
+ if (mInside != inside) {
+ if (mAnimator != null) {
+ mAnimator.outside();
+ }
+ mInside = inside;
+ }
+ }
+
public RippleAnimator animate() {
if (mAnimator == null) {
mAnimator = new RippleAnimator(this);
@@ -125,8 +139,8 @@
public boolean draw(Canvas c, Paint p) {
final Rect bounds = mBounds;
final Rect padding = mPadding;
- final float dX = Math.max(mX, bounds.right - mX);
- final float dY = Math.max(mY, bounds.bottom - mY);
+ final float dX = Math.max(mX - bounds.left, bounds.right - mX);
+ final float dY = Math.max(mY - bounds.top, bounds.bottom - mY);
final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
final float enterState = mEnterState;
@@ -308,9 +322,11 @@
MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
// Pulse is a little more complicated.
- final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
- mTarget.mPulseState = pulseTime < 0 ? -1
- : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+ if (mTarget.mPulse) {
+ final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
+ mTarget.mPulseState = pulseTime < 0 ? -1
+ : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+ }
}
}
}
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 792d62a..3b9d513 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -25,12 +25,13 @@
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Ripple.RippleAnimator;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.drawable.Ripple.RippleAnimator;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.SparseArray;
import com.android.internal.R;
@@ -39,11 +40,13 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.util.Arrays;
/**
* Documentation pending.
*/
public class TouchFeedbackDrawable extends LayerDrawable {
+ private static final String LOG_TAG = TouchFeedbackDrawable.class.getSimpleName();
private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
/** The maximum number of ripples supported. */
@@ -52,6 +55,9 @@
private final Rect mTempRect = new Rect();
private final Rect mPaddingRect = new Rect();
+ /** Current ripple effect bounds, used to constrain ripple effects. */
+ private final Rect mHotspotBounds = new Rect();
+
/** Current drawing bounds, used to compute dirty region. */
private final Rect mDrawingBounds = new Rect();
@@ -82,6 +88,9 @@
/** Whether the animation runnable has been posted. */
private boolean mAnimating;
+ /** Whether bounds are being overridden. */
+ private boolean mOverrideBounds;
+
TouchFeedbackDrawable() {
this(new TouchFeedbackState(null, null, null), null, null);
}
@@ -110,6 +119,47 @@
return false;
}
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+
+ if (!mOverrideBounds) {
+ mHotspotBounds.set(bounds);
+ }
+
+ onHotspotBoundsChange();
+ }
+
+ private void onHotspotBoundsChange() {
+ final int x = mHotspotBounds.centerX();
+ final int y = mHotspotBounds.centerY();
+ final int N = mActiveRipplesCount;
+ for (int i = 0; i < N; i++) {
+ if (mState.mPinned) {
+ mActiveRipples[i].move(x, y);
+ }
+ mActiveRipples[i].onBoundsChanged();
+ }
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ if (!visible) {
+ if (mTouchedRipples != null) {
+ mTouchedRipples.clear();
+ }
+
+ if (mActiveRipplesCount > 0) {
+ Arrays.fill(mActiveRipples, null);
+ mActiveRipplesCount = 0;
+ mAnimating = false;
+ unscheduleSelf(mAnimationRunnable);
+ }
+ }
+
+ return super.setVisible(visible, restart);
+ }
+
/**
* @hide
*/
@@ -260,24 +310,36 @@
mTouchedRipples = new SparseArray<Ripple>();
mActiveRipples = new Ripple[MAX_RIPPLES];
}
+
+ if (mActiveRipplesCount >= MAX_RIPPLES) {
+ Log.e(LOG_TAG, "Max ripple count exceeded", new RuntimeException());
+ return;
+ }
final Ripple ripple = mTouchedRipples.get(id);
if (ripple == null) {
- final Rect bounds = getBounds();
final Rect padding = mPaddingRect;
getPadding(padding);
+ final Rect bounds = mHotspotBounds;
if (mState.mPinned) {
x = bounds.exactCenterX();
y = bounds.exactCenterY();
}
- final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity);
+ // TODO: Clean this up in the API.
+ final boolean pulse = (id != R.attr.state_focused);
+ final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity, pulse);
newRipple.animate().enter();
mActiveRipples[mActiveRipplesCount++] = newRipple;
mTouchedRipples.put(id, newRipple);
- } else if (!mState.mPinned) {
+ } else if (mState.mPinned) {
+ final Rect bounds = mHotspotBounds;
+ x = bounds.exactCenterX();
+ y = bounds.exactCenterY();
+ ripple.move(x, y);
+ } else {
ripple.move(x, y);
}
@@ -307,6 +369,7 @@
final int n = mTouchedRipples.size();
for (int i = 0; i < n; i++) {
+ // TODO: Use a fast exit, maybe just fade out?
mTouchedRipples.valueAt(i).animate().exit();
}
@@ -317,6 +380,16 @@
}
/**
+ * @hide
+ */
+ @Override
+ public void setHotspotBounds(int left, int top, int right, int bottom) {
+ mOverrideBounds = true;
+ mHotspotBounds.set(left, top, right, bottom);
+ onHotspotBoundsChange();
+ }
+
+ /**
* Schedules the next animation, if necessary.
*/
private void scheduleAnimation() {
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 10c5fb8..2008f02 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -26,6 +26,7 @@
#include "Debug.h"
#include "DisplayListOp.h"
#include "DisplayListLogBuffer.h"
+#include "utils/MathUtils.h"
namespace android {
namespace uirenderer {
@@ -217,7 +218,9 @@
mat4 anim(*properties().getAnimationMatrix());
matrix.multiply(anim);
}
- if (properties().hasTransformMatrix()) {
+
+ bool applyTranslationZ = true3dTransform && !MathUtils::isZero(properties().getTranslationZ());
+ if (properties().hasTransformMatrix() || applyTranslationZ) {
if (properties().isTransformTranslateOnly()) {
matrix.translate(properties().getTranslationX(), properties().getTranslationY(),
true3dTransform ? properties().getTranslationZ() : 0.0f);
@@ -394,7 +397,7 @@
RenderNode* child = childOp->mDisplayList;
float childZ = child->properties().getTranslationZ();
- if (childZ != 0.0f) {
+ if (!MathUtils::isZero(childZ)) {
zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp));
childOp->mSkipInOrderDraw = true;
} else if (!child->properties().getProjectBackwards()) {
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 08829ef..a922db8 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -26,16 +26,7 @@
#include <SkPathOps.h>
#include "Matrix.h"
-
-/**
- * Convenience value to check for float values that are close enough to zero to be considered
- * zero.
- */
-#define NONZERO_EPSILON .001f
-
-static inline bool is_zero(float value) {
- return (value >= -NONZERO_EPSILON) || (value <= NONZERO_EPSILON);
-}
+#include "utils/MathUtils.h"
namespace android {
namespace uirenderer {
@@ -151,7 +142,7 @@
}
SkMatrix* transform = mComputedFields.mTransformMatrix;
transform->reset();
- if (is_zero(getRotationX()) && is_zero(getRotationY())) {
+ if (MathUtils::isZero(getRotationX()) && MathUtils::isZero(getRotationY())) {
transform->setTranslate(getTranslationX(), getTranslationY());
transform->preRotate(getRotation(), getPivotX(), getPivotY());
transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 5187f8f..d22cb8a 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -42,6 +42,7 @@
Font::Font(FontRenderer* state, const Font::FontDescription& desc) :
mState(state), mDescription(desc) {
+ mDeviceProperties = SkDeviceProperties::Make(SkDeviceProperties::Geometry::MakeDefault(), 1.0f);
}
Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix) {
@@ -272,7 +273,7 @@
if (cachedGlyph) {
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
- SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+ SkAutoGlyphCache autoCache(*paint, &mDeviceProperties, &mDescription.mLookupTransform);
const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), textUnit);
updateGlyphCache(paint, skiaGlyph, autoCache.getCache(), cachedGlyph, precaching);
}
@@ -464,7 +465,7 @@
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
- SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+ SkAutoGlyphCache autoCache(*paint, &mDeviceProperties, &mDescription.mLookupTransform);
const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), glyph);
newGlyph->mIsValid = false;
newGlyph->mGlyphIndex = skiaGlyph.fID;
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 02197bc..6ddd4f2 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -19,6 +19,8 @@
#include <utils/KeyedVector.h>
+#include <SkScalar.h>
+#include <SkDeviceProperties.h>
#include <SkGlyphCache.h>
#include <SkScalerContext.h>
#include <SkPaint.h>
@@ -146,6 +148,7 @@
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
bool mIdentityTransform;
+ SkDeviceProperties mDeviceProperties;
};
inline int strictly_order_type(const Font::FontDescription& lhs,
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
new file mode 100644
index 0000000..57ba8fa
--- /dev/null
+++ b/libs/hwui/utils/MathUtils.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+#ifndef MATHUTILS_H
+#define MATHUTILS_H
+
+namespace android {
+namespace uirenderer {
+
+class MathUtils {
+private:
+ static const float gNonZeroEpsilon = 0.001f;
+public:
+ /**
+ * Check for floats that are close enough to zero.
+ */
+ inline static bool isZero(float value) {
+ return (value >= -gNonZeroEpsilon) && (value <= gNonZeroEpsilon);
+ }
+}; // class MathUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* RENDERNODE_H */
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 214306c..2dea509 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -327,13 +327,12 @@
private static final int MSG_REEVALUATE_REMOTE = 3;
private static final int MSG_RCC_NEW_PLAYBACK_INFO = 4;
private static final int MSG_RCC_NEW_VOLUME_OBS = 5;
- private static final int MSG_PROMOTE_RCC = 6;
- private static final int MSG_RCC_NEW_PLAYBACK_STATE = 7;
- private static final int MSG_RCC_SEEK_REQUEST = 8;
- private static final int MSG_RCC_UPDATE_METADATA = 9;
- private static final int MSG_RCDISPLAY_INIT_INFO = 10;
- private static final int MSG_REEVALUATE_RCD = 11;
- private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 12;
+ private static final int MSG_RCC_NEW_PLAYBACK_STATE = 6;
+ private static final int MSG_RCC_SEEK_REQUEST = 7;
+ private static final int MSG_RCC_UPDATE_METADATA = 8;
+ private static final int MSG_RCDISPLAY_INIT_INFO = 9;
+ private static final int MSG_REEVALUATE_RCD = 10;
+ private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 11;
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
@@ -406,10 +405,6 @@
(Rating) msg.obj /* value */);
break;
- case MSG_PROMOTE_RCC:
- onPromoteRcc(msg.arg1);
- break;
-
case MSG_RCDISPLAY_INIT_INFO:
// msg.obj is guaranteed to be non null
onRcDisplayInitInfo((IRemoteControlDisplay)msg.obj /*newRcd*/,
@@ -1212,56 +1207,91 @@
mediaButtonIntent.setComponent(eventReceiver);
PendingIntent pi = PendingIntent.getBroadcast(mContext,
0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
- registerMediaButtonIntent(pi, eventReceiver, null);
+ registerMediaButtonIntent(pi, eventReceiver, null /*token*/);
}
}
/**
* Helper function:
- * Set the new remote control receiver at the top of the RC focus stack.
+ * Push the new media button receiver "near" the top of the PlayerRecord stack.
+ * "Near the top" is defined as:
+ * - at the top if the current PlayerRecord at the top is not playing
+ * - below the entries at the top of the stack that correspond to the playing PlayerRecord
+ * otherwise
* Called synchronized on mPRStack
* precondition: mediaIntent != null
- * @return true if mPRStack was changed, false otherwise
+ * @return true if the top of mPRStack was changed, false otherwise
*/
private boolean pushMediaButtonReceiver_syncPrs(PendingIntent mediaIntent,
ComponentName target, IBinder token) {
- // already at top of stack?
- if (!mPRStack.empty() && mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
+ if (mPRStack.empty()) {
+ mPRStack.push(new PlayerRecord(mediaIntent, target, token));
+ return true;
+ } else if (mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
+ // already at top of stack
return false;
}
if (mAppOps.noteOp(AppOpsManager.OP_TAKE_MEDIA_BUTTONS, Binder.getCallingUid(),
mediaIntent.getCreatorPackage()) != AppOpsManager.MODE_ALLOWED) {
return false;
}
+ PlayerRecord oldTopPrse = mPRStack.lastElement(); // top of the stack before any changes
+ boolean topChanged = false;
PlayerRecord prse = null;
- boolean wasInsideStack = false;
+ int lastPlayingIndex = mPRStack.size();
+ int inStackIndex = -1;
try {
+ // go through the stack from the top to figure out who's playing, and the position
+ // of this media button receiver (note that it may not be in the stack)
for (int index = mPRStack.size()-1; index >= 0; index--) {
prse = mPRStack.elementAt(index);
- if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
- // ok to remove element while traversing the stack since we're leaving the loop
- mPRStack.removeElementAt(index);
- wasInsideStack = true;
+ if (prse.isPlaybackActive()) {
+ lastPlayingIndex = index;
+ }
+ if (prse.hasMatchingMediaButtonIntent(mediaIntent)) {
+ inStackIndex = index;
+ // found it, ok to stop here
break;
}
}
+
+ if (inStackIndex == -1) {
+ // is not in stack
+ prse = new PlayerRecord(mediaIntent, target, token);
+ // it's new so it's not playing (no RemoteControlClient to give a playstate),
+ // therefore it goes after the ones with active playback
+ mPRStack.add(lastPlayingIndex, prse);
+ } else {
+ // is in the stack
+ if (mPRStack.size() > 1) { // no need to remove and add if stack contains only 1
+ prse = mPRStack.elementAt(inStackIndex);
+ // remove it from its old location in the stack
+ mPRStack.removeElementAt(inStackIndex);
+ if (prse.isPlaybackActive()) {
+ // and put it at the top
+ mPRStack.push(prse);
+ } else {
+ // and put it after the ones with active playback
+ mPRStack.add(lastPlayingIndex, prse);
+ }
+ }
+ }
+
+ topChanged = (oldTopPrse != mPRStack.lastElement());
+ // post message to persist the default media button receiver
+ if (topChanged && (target != null)) {
+ mEventHandler.sendMessage( mEventHandler.obtainMessage(
+ MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+ }
+
} catch (ArrayIndexOutOfBoundsException e) {
- // not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e);
- }
- if (!wasInsideStack) {
- prse = new PlayerRecord(mediaIntent, target, token);
- }
- mPRStack.push(prse); // prse is never null
-
- // post message to persist the default media button receiver
- if (target != null) {
- mEventHandler.sendMessage( mEventHandler.obtainMessage(
- MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+ // not expected to happen, indicates improper concurrent modification or bad index
+ Log.e(TAG, "Wrong index (inStack=" + inStackIndex + " lastPlaying=" + lastPlayingIndex
+ + " size=" + mPRStack.size()
+ + " accessing media button stack", e);
}
- // RC stack was modified
- return true;
+ return (topChanged);
}
/**
@@ -1515,48 +1545,6 @@
}
/**
- * Helper function:
- * Post a message to asynchronously move the media button event receiver associated with the
- * given remote control client ID to the top of the remote control stack
- * @param rccId
- */
- private void postPromoteRcc(int rccId) {
- sendMsg(mEventHandler, MSG_PROMOTE_RCC, SENDMSG_REPLACE,
- rccId /*arg1*/, 0, null, 0/*delay*/);
- }
-
- private void onPromoteRcc(int rccId) {
- if (DEBUG_RC) { Log.d(TAG, "Promoting RCC " + rccId); }
- synchronized(mPRStack) {
- // ignore if given RCC ID is already at top of remote control stack
- if (!mPRStack.isEmpty() && (mPRStack.peek().getRccId() == rccId)) {
- return;
- }
- int indexToPromote = -1;
- try {
- for (int index = mPRStack.size()-1; index >= 0; index--) {
- final PlayerRecord prse = mPRStack.elementAt(index);
- if (prse.getRccId() == rccId) {
- indexToPromote = index;
- break;
- }
- }
- if (indexToPromote >= 0) {
- if (DEBUG_RC) { Log.d(TAG, " moving RCC from index " + indexToPromote
- + " to " + (mPRStack.size()-1)); }
- final PlayerRecord prse = mPRStack.remove(indexToPromote);
- mPRStack.push(prse);
- // the RC stack changed, reevaluate the display
- checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- // not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
- }
- }//synchronized(mPRStack)
- }
-
- /**
* see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
* precondition: mediaIntent != null
*/
@@ -2151,30 +2139,66 @@
if(DEBUG_RC) Log.d(TAG, "onNewPlaybackStateForRcc(id=" + rccId + ", state=" + state
+ ", time=" + newState.mPositionMs + ", speed=" + newState.mSpeed + ")");
synchronized(mPRStack) {
- // iterating from top of stack as playback information changes are more likely
- // on entries at the top of the remote control stack
+ if (mPRStack.empty()) {
+ return;
+ }
+ PlayerRecord oldTopPrse = mPRStack.lastElement(); // top of the stack before any changes
+ PlayerRecord prse = null;
+ int lastPlayingIndex = mPRStack.size();
+ int inStackIndex = -1;
try {
+ // go through the stack from the top to figure out who's playing, and the position
+ // of this RemoteControlClient (note that it may not be in the stack)
for (int index = mPRStack.size()-1; index >= 0; index--) {
- final PlayerRecord prse = mPRStack.elementAt(index);
+ prse = mPRStack.elementAt(index);
+ if (prse.isPlaybackActive()) {
+ lastPlayingIndex = index;
+ }
if (prse.getRccId() == rccId) {
+ inStackIndex = index;
prse.mPlaybackState = newState;
- synchronized (mMainRemote) {
- if (rccId == mMainRemote.mRccId) {
- mMainRemoteIsActive = isPlaystateActive(state);
- postReevaluateRemote();
- }
- }
- // an RCC moving to a "playing" state should become the media button
- // event receiver so it can be controlled, without requiring the
- // app to re-register its receiver
- if (isPlaystateActive(state)) {
- postPromoteRcc(rccId);
+ }
+ }
+
+ if (inStackIndex != -1) {
+ // is in the stack
+ prse = mPRStack.elementAt(inStackIndex);
+ synchronized (mMainRemote) {
+ if (rccId == mMainRemote.mRccId) {
+ mMainRemoteIsActive = isPlaystateActive(state);
+ postReevaluateRemote();
}
}
- }//for
+ if (mPRStack.size() > 1) { // no need to remove and add if stack contains only 1
+ // remove it from its old location in the stack
+ mPRStack.removeElementAt(inStackIndex);
+ if (prse.isPlaybackActive()) {
+ // and put it at the top
+ mPRStack.push(prse);
+ } else {
+ // and put it after the ones with active playback
+ mPRStack.add(lastPlayingIndex, prse);
+ }
+ }
+
+ if (oldTopPrse != mPRStack.lastElement()) {
+ // the top of the stack changed:
+ final ComponentName target =
+ mPRStack.lastElement().getMediaButtonReceiver();
+ if (target != null) {
+ // post message to persist the default media button receiver
+ mEventHandler.sendMessage( mEventHandler.obtainMessage(
+ MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+ }
+ // reevaluate the display
+ checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
+ }
+ }
} catch (ArrayIndexOutOfBoundsException e) {
- // not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index on mPRStack in onNewPlaybackStateForRcc, lock error? ", e);
+ // not expected to happen, indicates improper concurrent modification or bad index
+ Log.e(TAG, "Wrong index (inStack=" + inStackIndex + " lastPlaying=" + lastPlayingIndex
+ + " size=" + mPRStack.size()
+ + "accessing PlayerRecord stack in onNewPlaybackStateForRcc", e);
}
}
}
@@ -2249,7 +2273,7 @@
* @param playState the playback state to evaluate
* @return true if active, false otherwise (inactive or unknown)
*/
- private static boolean isPlaystateActive(int playState) {
+ protected static boolean isPlaystateActive(int playState) {
switch (playState) {
case RemoteControlClient.PLAYSTATE_PLAYING:
case RemoteControlClient.PLAYSTATE_BUFFERING:
diff --git a/media/java/android/media/PlayerRecord.java b/media/java/android/media/PlayerRecord.java
index a79b0ed..f9708c3 100644
--- a/media/java/android/media/PlayerRecord.java
+++ b/media/java/android/media/PlayerRecord.java
@@ -58,6 +58,9 @@
private int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
+ /**
+ * A non-null token implies this record tracks a "live" player whose death is being monitored.
+ */
private IBinder mToken;
private String mCallingPackageName;
private int mCallingUid;
@@ -254,20 +257,20 @@
return mMediaIntent;
}
- // FIXME this is only used when comparing with the audio focus owner calling package name,
- // accessor to be removed once audio focus and media button owner are dissociated
- protected String getCallingPackageName() {
- return mCallingPackageName;
- }
-
- // FIXME this is only used when comparing with the audio focus owner calling package name,
- // accessor to be removed once audio focus and media button owner are dissociated
- protected int getCallingUid() {
- return mCallingUid;
- }
-
protected boolean hasMatchingMediaButtonIntent(PendingIntent pi) {
- return mMediaIntent.equals(pi);
+ if (mToken != null) {
+ return mMediaIntent.equals(pi);
+ } else {
+ if (mReceiverComponent != null) {
+ return mReceiverComponent.equals(pi.getIntent().getComponent());
+ } else {
+ return false;
+ }
+ }
+ }
+
+ protected boolean isPlaybackActive() {
+ return MediaFocusControl.isPlaystateActive(mPlaybackState.mState);
}
//---------------------------------------------
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
deleted file mode 100644
index c5cc2ca..0000000
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-
-/**
- * This class allows to handle an audio track. This audio file is mixed with the
- * audio samples of the media items.
- * {@hide}
- */
-public class AudioTrack {
-
- /**
- * Instance variables
- * Private object for calling native methods via MediaArtistNativeHelper
- */
- private final MediaArtistNativeHelper mMANativeHelper;
- private final String mUniqueId;
- private final String mFilename;
- private long mStartTimeMs;
- private long mTimelineDurationMs;
- private int mVolumePercent;
- private long mBeginBoundaryTimeMs;
- private long mEndBoundaryTimeMs;
- private boolean mLoop;
- private boolean mMuted;
- private final long mDurationMs;
- private final int mAudioChannels;
- private final int mAudioType;
- private final int mAudioBitrate;
- private final int mAudioSamplingFrequency;
- /**
- * Ducking variables
- */
- private int mDuckingThreshold;
- private int mDuckedTrackVolume;
- private boolean mIsDuckingEnabled;
-
- /**
- * The audio waveform filename
- */
- private String mAudioWaveformFilename;
-
- /**
- * The audio waveform data
- */
- private SoftReference<WaveformData> mWaveformData;
-
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private AudioTrack() throws IOException {
- this(null, null, null);
- }
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param audioTrackId The audio track id
- * @param filename The absolute file name
- *
- * @throws IOException if file is not found
- * @throws IllegalArgumentException if file format is not supported or if
- * the codec is not supported or if editor is not of type
- * VideoEditorImpl.
- */
- public AudioTrack(VideoEditor editor, String audioTrackId, String filename) throws IOException {
- this(editor, audioTrackId, filename, 0, 0, MediaItem.END_OF_FILE, false, 100, false, false,
- 0, 0, null);
- }
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param audioTrackId The audio track id
- * @param filename The audio filename. In case file contains Audio and Video,
- * only the Audio stream will be used as Audio Track.
- * @param startTimeMs the start time in milliseconds (relative to the
- * timeline)
- * @param beginMs start time in the audio track in milliseconds (relative to
- * the beginning of the audio track)
- * @param endMs end time in the audio track in milliseconds (relative to the
- * beginning of the audio track)
- * @param loop true to loop the audio track
- * @param volume The volume in percentage
- * @param muted true if the audio track is muted
- * @param threshold Ducking will be activated when the relative energy in
- * the media items audio signal goes above this value. The valid
- * range of values is 0 to 90.
- * @param duckedTrackVolume The relative volume of the audio track when
- * ducking is active. The valid range of values is 0 to 100.
- * @param audioWaveformFilename The name of the waveform file
- *
- * @throws IOException if file is not found
- * @throws IllegalArgumentException if file format is not supported or if
- * the codec is not supported or if editor is not of type
- * VideoEditorImpl.
- */
- AudioTrack(VideoEditor editor, String audioTrackId, String filename,
- long startTimeMs,long beginMs, long endMs, boolean loop,
- int volume, boolean muted,boolean duckingEnabled,
- int duckThreshold, int duckedTrackVolume,
- String audioWaveformFilename) throws IOException {
- Properties properties = null;
-
- File file = new File(filename);
- if (!file.exists()) {
- throw new IOException(filename + " not found ! ");
- }
-
- /*Compare file_size with 2GB*/
- if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) {
- throw new IllegalArgumentException("File size is more than 2GB");
- }
-
- if (editor instanceof VideoEditorImpl) {
- mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
- } else {
- throw new IllegalArgumentException("editor is not of type VideoEditorImpl");
- }
- try {
- properties = mMANativeHelper.getMediaProperties(filename);
- } catch (Exception e) {
- throw new IllegalArgumentException(e.getMessage() + " : " + filename);
- }
- int fileType = mMANativeHelper.getFileType(properties.fileType);
- switch (fileType) {
- case MediaProperties.FILE_3GP:
- case MediaProperties.FILE_MP4:
- case MediaProperties.FILE_MP3:
- case MediaProperties.FILE_AMR:
- break;
-
- default: {
- throw new IllegalArgumentException("Unsupported input file type: " + fileType);
- }
- }
- switch (mMANativeHelper.getAudioCodecType(properties.audioFormat)) {
- case MediaProperties.ACODEC_AMRNB:
- case MediaProperties.ACODEC_AMRWB:
- case MediaProperties.ACODEC_AAC_LC:
- case MediaProperties.ACODEC_MP3:
- break;
- default:
- throw new IllegalArgumentException("Unsupported Audio Codec Format in Input File");
- }
-
- if (endMs == MediaItem.END_OF_FILE) {
- endMs = properties.audioDuration;
- }
-
- mUniqueId = audioTrackId;
- mFilename = filename;
- mStartTimeMs = startTimeMs;
- mDurationMs = properties.audioDuration;
- mAudioChannels = properties.audioChannels;
- mAudioBitrate = properties.audioBitrate;
- mAudioSamplingFrequency = properties.audioSamplingFrequency;
- mAudioType = properties.audioFormat;
- mTimelineDurationMs = endMs - beginMs;
- mVolumePercent = volume;
-
- mBeginBoundaryTimeMs = beginMs;
- mEndBoundaryTimeMs = endMs;
-
- mLoop = loop;
- mMuted = muted;
- mIsDuckingEnabled = duckingEnabled;
- mDuckingThreshold = duckThreshold;
- mDuckedTrackVolume = duckedTrackVolume;
-
- mAudioWaveformFilename = audioWaveformFilename;
- if (audioWaveformFilename != null) {
- mWaveformData =
- new SoftReference<WaveformData>(new WaveformData(audioWaveformFilename));
- } else {
- mWaveformData = null;
- }
- }
-
- /**
- * Get the id of the audio track
- *
- * @return The id of the audio track
- */
- public String getId() {
- return mUniqueId;
- }
-
- /**
- * Get the filename for this audio track source.
- *
- * @return The filename as an absolute file name
- */
- public String getFilename() {
- return mFilename;
- }
-
- /**
- * Get the number of audio channels in the source of this audio track
- *
- * @return The number of audio channels in the source of this audio track
- */
- public int getAudioChannels() {
- return mAudioChannels;
- }
-
- /**
- * Get the audio codec of the source of this audio track
- *
- * @return The audio codec of the source of this audio track
- * {@link android.media.videoeditor.MediaProperties}
- */
- public int getAudioType() {
- return mAudioType;
- }
-
- /**
- * Get the audio sample frequency of the audio track
- *
- * @return The audio sample frequency of the audio track
- */
- public int getAudioSamplingFrequency() {
- return mAudioSamplingFrequency;
- }
-
- /**
- * Get the audio bitrate of the audio track
- *
- * @return The audio bitrate of the audio track
- */
- public int getAudioBitrate() {
- return mAudioBitrate;
- }
-
- /**
- * Set the volume of this audio track as percentage of the volume in the
- * original audio source file.
- *
- * @param volumePercent Percentage of the volume to apply. If it is set to
- * 0, then volume becomes mute. It it is set to 100, then volume
- * is same as original volume. It it is set to 200, then volume
- * is doubled (provided that volume amplification is supported)
- *
- * @throws UnsupportedOperationException if volume amplification is
- * requested and is not supported.
- */
- public void setVolume(int volumePercent) {
- if (volumePercent > MediaProperties.AUDIO_MAX_VOLUME_PERCENT) {
- throw new IllegalArgumentException("Volume set exceeds maximum allowed value");
- }
-
- if (volumePercent < 0) {
- throw new IllegalArgumentException("Invalid Volume ");
- }
-
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
-
- mVolumePercent = volumePercent;
- }
-
- /**
- * Get the volume of the audio track as percentage of the volume in the
- * original audio source file.
- *
- * @return The volume in percentage
- */
- public int getVolume() {
- return mVolumePercent;
- }
-
- /**
- * Mute/Unmute the audio track
- *
- * @param muted true to mute the audio track. SetMute(true) will make
- * the volume of this Audio Track to 0.
- */
- public void setMute(boolean muted) {
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
- mMuted = muted;
- }
-
- /**
- * Check if the audio track is muted
- *
- * @return true if the audio track is muted
- */
- public boolean isMuted() {
- return mMuted;
- }
-
- /**
- * Get the start time of this audio track relative to the storyboard
- * timeline.
- *
- * @return The start time in milliseconds
- */
-
- public long getStartTime() {
- return mStartTimeMs;
- }
-
- /**
- * Get the audio track duration
- *
- * @return The duration in milliseconds. This value represents actual audio
- * track duration. This value is not effected by 'enableLoop' or
- * 'setExtractBoundaries'.
- */
- public long getDuration() {
- return mDurationMs;
- }
-
- /**
- * Get the audio track timeline duration
- *
- * @return The timeline duration as defined by the begin and end boundaries
- */
- public long getTimelineDuration() {
- return mTimelineDurationMs;
- }
-
- /**
- * Sets the start and end marks for trimming an audio track
- *
- * @param beginMs start time in the audio track in milliseconds (relative to
- * the beginning of the audio track)
- * @param endMs end time in the audio track in milliseconds (relative to the
- * beginning of the audio track)
- */
- public void setExtractBoundaries(long beginMs, long endMs) {
- if (beginMs > mDurationMs) {
- throw new IllegalArgumentException("Invalid start time");
- }
- if (endMs > mDurationMs) {
- throw new IllegalArgumentException("Invalid end time");
- }
- if (beginMs < 0) {
- throw new IllegalArgumentException("Invalid start time; is < 0");
- }
- if (endMs < 0) {
- throw new IllegalArgumentException("Invalid end time; is < 0");
- }
-
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
-
- mBeginBoundaryTimeMs = beginMs;
- mEndBoundaryTimeMs = endMs;
-
- mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
- }
-
- /**
- * Get the boundary begin time
- *
- * @return The boundary begin time
- */
- public long getBoundaryBeginTime() {
- return mBeginBoundaryTimeMs;
- }
-
- /**
- * Get the boundary end time
- *
- * @return The boundary end time
- */
- public long getBoundaryEndTime() {
- return mEndBoundaryTimeMs;
- }
-
- /**
- * Enable the loop mode for this audio track. Note that only one of the
- * audio tracks in the timeline can have the loop mode enabled. When looping
- * is enabled the samples between mBeginBoundaryTimeMs and
- * mEndBoundaryTimeMs are looped.
- */
- public void enableLoop() {
- if (!mLoop) {
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
- mLoop = true;
- }
- }
-
- /**
- * Disable the loop mode
- */
- public void disableLoop() {
- if (mLoop) {
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
- mLoop = false;
- }
- }
-
- /**
- * Check if looping is enabled
- *
- * @return true if looping is enabled
- */
- public boolean isLooping() {
- return mLoop;
- }
-
- /**
- * Disable the audio duck effect
- */
- public void disableDucking() {
- if (mIsDuckingEnabled) {
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
- mIsDuckingEnabled = false;
- }
- }
-
- /**
- * Enable ducking by specifying the required parameters
- *
- * @param threshold Ducking will be activated when the energy in
- * the media items audio signal goes above this value. The valid
- * range of values is 0db to 90dB. 0dB is equivalent to disabling
- * ducking.
- * @param duckedTrackVolume The relative volume of the audio track when ducking
- * is active. The valid range of values is 0 to 100.
- */
- public void enableDucking(int threshold, int duckedTrackVolume) {
- if (threshold < 0 || threshold > 90) {
- throw new IllegalArgumentException("Invalid threshold value: " + threshold);
- }
-
- if (duckedTrackVolume < 0 || duckedTrackVolume > 100) {
- throw new IllegalArgumentException("Invalid duckedTrackVolume value: "
- + duckedTrackVolume);
- }
-
- /**
- * Force update of preview settings
- */
- mMANativeHelper.setGeneratePreview(true);
-
- mDuckingThreshold = threshold;
- mDuckedTrackVolume = duckedTrackVolume;
- mIsDuckingEnabled = true;
- }
-
- /**
- * Check if ducking is enabled
- *
- * @return true if ducking is enabled
- */
- public boolean isDuckingEnabled() {
- return mIsDuckingEnabled;
- }
-
- /**
- * Get the ducking threshold.
- *
- * @return The ducking threshold
- */
- public int getDuckingThreshhold() {
- return mDuckingThreshold;
- }
-
- /**
- * Get the ducked track volume.
- *
- * @return The ducked track volume
- */
- public int getDuckedTrackVolume() {
- return mDuckedTrackVolume;
- }
-
- /**
- * This API allows to generate a file containing the sample volume levels of
- * this audio track object. This function may take significant time and is
- * blocking. The filename can be retrieved using getAudioWaveformFilename().
- *
- * @param listener The progress listener
- *
- * @throws IOException if the output file cannot be created
- * @throws IllegalArgumentException if the audio file does not have a valid
- * audio track
- * @throws IllegalStateException if the codec type is unsupported
- */
- public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
- throws IOException {
- if (mAudioWaveformFilename == null) {
- /**
- * AudioWaveformFilename is generated
- */
- final String projectPath = mMANativeHelper.getProjectPath();
- final String audioWaveFilename = String.format(projectPath + "/audioWaveformFile-"
- + getId() + ".dat");
-
- /**
- * Logic to get frame duration = (no. of frames per sample * 1000)/
- * sampling frequency
- */
- final int frameDuration;
- final int sampleCount;
- final int codecType = mMANativeHelper.getAudioCodecType(mAudioType);
- switch (codecType) {
- case MediaProperties.ACODEC_AMRNB: {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB * 1000)
- / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB;
- break;
- }
-
- case MediaProperties.ACODEC_AMRWB: {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)
- / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB;
- break;
- }
-
- case MediaProperties.ACODEC_AAC_LC: {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)
- / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AAC;
- break;
- }
-
- case MediaProperties.ACODEC_MP3: {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_MP3 * 1000)
- / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_MP3;
- break;
- }
-
- default: {
- throw new IllegalStateException("Unsupported codec type: "
- + codecType);
- }
- }
-
- mMANativeHelper.generateAudioGraph( mUniqueId,
- mFilename,
- audioWaveFilename,
- frameDuration,
- MediaProperties.DEFAULT_CHANNEL_COUNT,
- sampleCount,
- listener,
- false);
- /**
- * Record the generated file name
- */
- mAudioWaveformFilename = audioWaveFilename;
- }
- mWaveformData = new SoftReference<WaveformData>(new WaveformData(mAudioWaveformFilename));
- }
-
- /**
- * Get the audio waveform file name if extractAudioWaveform was successful.
- *
- * @return the name of the file, null if the file does not exist
- */
- String getAudioWaveformFilename() {
- return mAudioWaveformFilename;
- }
-
- /**
- * Delete the waveform file
- */
- void invalidate() {
- if (mAudioWaveformFilename != null) {
- new File(mAudioWaveformFilename).delete();
- mAudioWaveformFilename = null;
- mWaveformData = null;
- }
- }
-
- /**
- * Get the audio waveform data.
- *
- * @return The waveform data
- *
- * @throws IOException if the waveform file cannot be found
- */
- public WaveformData getWaveformData() throws IOException {
- if (mWaveformData == null) {
- return null;
- }
-
- WaveformData waveformData = mWaveformData.get();
- if (waveformData != null) {
- return waveformData;
- } else if (mAudioWaveformFilename != null) {
- try {
- waveformData = new WaveformData(mAudioWaveformFilename);
- } catch (IOException e) {
- throw e;
- }
- mWaveformData = new SoftReference<WaveformData>(waveformData);
- return waveformData;
- } else {
- return null;
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof AudioTrack)) {
- return false;
- }
- return mUniqueId.equals(((AudioTrack)object).mUniqueId);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return mUniqueId.hashCode();
- }
-}
diff --git a/media/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
deleted file mode 100644
index 2f7ae03..0000000
--- a/media/java/android/media/videoeditor/Effect.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-/**
- * This is the super class for all effects. An effect can only be applied to a
- * single media item.
- * {@hide}
- */
-public abstract class Effect {
- /**
- * Instance variables
- */
- private final String mUniqueId;
- /**
- * The effect owner
- */
- private final MediaItem mMediaItem;
-
- protected long mDurationMs;
- /**
- * The start time of the effect relative to the beginning
- * of the media item
- */
- protected long mStartTimeMs;
-
- /**
- * Default constructor
- */
- @SuppressWarnings("unused")
- private Effect() {
- mMediaItem = null;
- mUniqueId = null;
- mStartTimeMs = 0;
- mDurationMs = 0;
- }
-
- /**
- * Constructor
- *
- * @param mediaItem The media item owner
- * @param effectId The effect id
- * @param startTimeMs The start time relative to the media item to which it
- * is applied
- * @param durationMs The effect duration in milliseconds
- */
- public Effect(MediaItem mediaItem, String effectId, long startTimeMs,
- long durationMs) {
- if (mediaItem == null) {
- throw new IllegalArgumentException("Media item cannot be null");
- }
-
- if ((startTimeMs < 0) || (durationMs < 0)) {
- throw new IllegalArgumentException("Invalid start time Or/And Duration");
- }
- if (startTimeMs + durationMs > mediaItem.getDuration()) {
- throw new IllegalArgumentException("Invalid start time and duration");
- }
-
- mMediaItem = mediaItem;
- mUniqueId = effectId;
- mStartTimeMs = startTimeMs;
- mDurationMs = durationMs;
- }
-
- /**
- * Get the id of the effect.
- *
- * @return The id of the effect
- */
- public String getId() {
- return mUniqueId;
- }
-
- /**
- * Set the duration of the effect. If a preview or export is in progress,
- * then this change is effective for next preview or export session.
- *
- * @param durationMs of the effect in milliseconds
- */
- public void setDuration(long durationMs) {
- if (durationMs <0) {
- throw new IllegalArgumentException("Invalid duration");
- }
-
- if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Duration is too large");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
-
- final long oldDurationMs = mDurationMs;
- mDurationMs = durationMs;
-
- mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the duration of the effect
- *
- * @return The duration of the effect in milliseconds
- */
- public long getDuration() {
- return mDurationMs;
- }
-
- /**
- * Set start time of the effect. If a preview or export is in progress, then
- * this change is effective for next preview or export session.
- *
- * @param startTimeMs The start time of the effect relative to the beginning
- * of the media item in milliseconds
- */
- public void setStartTime(long startTimeMs) {
- if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Start time is too large");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
- final long oldStartTimeMs = mStartTimeMs;
- mStartTimeMs = startTimeMs;
-
- mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the start time of the effect
- *
- * @return The start time in milliseconds
- */
- public long getStartTime() {
- return mStartTimeMs;
- }
-
- /**
- * Set the start time and duration
- *
- * @param startTimeMs start time in milliseconds
- * @param durationMs The duration in milliseconds
- */
- public void setStartTimeAndDuration(long startTimeMs, long durationMs) {
- if (startTimeMs + durationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Invalid start time or duration");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
- final long oldStartTimeMs = mStartTimeMs;
- final long oldDurationMs = mDurationMs;
-
- mStartTimeMs = startTimeMs;
- mDurationMs = durationMs;
-
- mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the media item owner.
- *
- * @return The media item owner
- */
- public MediaItem getMediaItem() {
- return mMediaItem;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof Effect)) {
- return false;
- }
- return mUniqueId.equals(((Effect)object).mUniqueId);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return mUniqueId.hashCode();
- }
-}
diff --git a/media/java/android/media/videoeditor/EffectColor.java b/media/java/android/media/videoeditor/EffectColor.java
deleted file mode 100644
index 6c5ac2d..0000000
--- a/media/java/android/media/videoeditor/EffectColor.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-/**
- * This class allows to apply color effect on a media item.
- * {@hide}
- */
-public class EffectColor extends Effect {
-
- /**
- * Change the video frame color to the RGB color value provided
- */
- public static final int TYPE_COLOR = 1;
- /**
- * Change the video frame color to a gradation from RGB color (at the top of
- * the frame) to black (at the bottom of the frame).
- */
- public static final int TYPE_GRADIENT = 2;
- /**
- * Change the video frame color to sepia
- */
- public static final int TYPE_SEPIA = 3;
- /**
- * Invert the video frame color
- */
- public static final int TYPE_NEGATIVE = 4;
- /**
- * Make the video look like as if it was recorded in 50's
- */
- public static final int TYPE_FIFTIES = 5;
- /**
- * Change the video frame color to the RGB color value GREEN
- */
- public static final int GREEN = 0x0000ff00;
- /**
- * Change the video frame color to the RGB color value PINK
- */
- public static final int PINK = 0x00ff66cc;
- /**
- * Change the video frame color to the RGB color value GRAY
- */
- public static final int GRAY = 0x007f7f7f;
-
- /**
- * The effect type
- */
- private final int mType;
-
- /**
- * The effect color
- */
- private final int mColor;
-
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private EffectColor() {
- this(null, null, 0, 0, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param mediaItem The media item owner
- * @param effectId The effect id
- * @param startTimeMs The start time relative to the media item to which it
- * is applied
- * @param durationMs The duration of this effect in milliseconds
- * @param type type of the effect. type is one of: TYPE_COLOR,
- * TYPE_GRADIENT, TYPE_SEPIA, TYPE_NEGATIVE, TYPE_FIFTIES.
- * @param color If type is TYPE_COLOR, color is the RGB color as 888.
- * If type is TYPE_GRADIENT, color is the RGB color at the
- * top of the frame. Otherwise, color is ignored
- */
- public EffectColor(MediaItem mediaItem, String effectId, long startTimeMs,
- long durationMs, int type, int color) {
- super(mediaItem, effectId, startTimeMs, durationMs);
- switch (type) {
- case TYPE_COLOR:
- case TYPE_GRADIENT: {
- switch (color) {
- case GREEN:
- case PINK:
- case GRAY:
- mColor = color;
- break;
-
- default:
- throw new IllegalArgumentException("Invalid Color: " + color);
- }
- break;
- }
- case TYPE_SEPIA:
- case TYPE_NEGATIVE:
- case TYPE_FIFTIES: {
- mColor = -1;
- break;
- }
-
- default: {
- throw new IllegalArgumentException("Invalid type: " + type);
- }
- }
- mType = type;
- }
-
- /**
- * Get the effect type.
- *
- * @return The effect type
- */
- public int getType() {
- return mType;
- }
-
- /**
- * Get the color if effect type is TYPE_COLOR or TYPE_GRADIENT.
- *
- * @return the color as RGB 888 if type is TYPE_COLOR or TYPE_GRADIENT.
- */
- public int getColor() {
- return mColor;
- }
-}
diff --git a/media/java/android/media/videoeditor/EffectKenBurns.java b/media/java/android/media/videoeditor/EffectKenBurns.java
deleted file mode 100644
index 64be6b8..0000000
--- a/media/java/android/media/videoeditor/EffectKenBurns.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import android.graphics.Rect;
-
-/**
- * This class represents a Ken Burns effect.
- * {@hide}
- */
-public class EffectKenBurns extends Effect {
- /**
- * Instance variables
- */
- private Rect mStartRect;
- private Rect mEndRect;
-
- /**
- * Objects of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private EffectKenBurns() {
- this(null, null, null, null, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param mediaItem The media item owner
- * @param effectId The effect id
- * @param startRect The start rectangle
- * @param endRect The end rectangle
- * @param startTimeMs The start time
- * @param durationMs The duration of the Ken Burns effect in milliseconds
- */
- public EffectKenBurns(MediaItem mediaItem, String effectId, Rect startRect,
- Rect endRect, long startTimeMs, long durationMs) {
- super(mediaItem, effectId, startTimeMs, durationMs);
-
- if ( (startRect.width() <= 0) || (startRect.height() <= 0) ) {
- throw new IllegalArgumentException("Invalid Start rectangle");
- }
- if ( (endRect.width() <= 0) || (endRect.height() <= 0) ) {
- throw new IllegalArgumentException("Invalid End rectangle");
- }
-
- mStartRect = startRect;
- mEndRect = endRect;
- }
-
-
- /**
- * Get the start rectangle.
- *
- * @return The start rectangle
- */
- public Rect getStartRect() {
- return mStartRect;
- }
-
-
- /**
- * Get the end rectangle.
- *
- * @return The end rectangle
- */
- public Rect getEndRect() {
- return mEndRect;
- }
-
- /**
- * Get the KenBurn effect start and end rectangle coordinates
- * @param start The rect object to be populated with start
- * rectangle coordinates
- *
- * @param end The rect object to be populated with end
- * rectangle coordinates
- */
- void getKenBurnsSettings(Rect start, Rect end) {
- start.left = getStartRect().left;
- start.top = getStartRect().top;
- start.right = getStartRect().right;
- start.bottom = getStartRect().bottom;
- end.left = getEndRect().left;
- end.top = getEndRect().top;
- end.right = getEndRect().right;
- end.bottom = getEndRect().bottom;
- }
-}
diff --git a/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java b/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java
deleted file mode 100644
index 7ba7de3..0000000
--- a/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-/**
- * This listener interface is used by
- * {@link MediaVideoItem#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
- * or
- * {@link AudioTrack#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
- * {@hide}
- */
-public interface ExtractAudioWaveformProgressListener {
- /**
- * This method notifies the listener of the progress status of
- * an extractAudioWaveform operation.
- * This method may be called maximum 100 times for one operation.
- *
- * @param progress The progress in %. At the beginning of the operation,
- * this value is set to 0; at the end, the value is set to 100.
- */
- public void onProgress(int progress);
-}
-
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
deleted file mode 100644
index 2d3de85..0000000
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ /dev/null
@@ -1,4034 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.nio.IntBuffer;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Matrix;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.PreviewProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Surface;
-
-/**
- *This class provide Native methods to be used by MediaArtist {@hide}
- */
-class MediaArtistNativeHelper {
- private static final String TAG = "MediaArtistNativeHelper";
-
- static {
- System.loadLibrary("videoeditor_jni");
- }
-
- private static final int MAX_THUMBNAIL_PERMITTED = 8;
-
- public static final int TASK_LOADING_SETTINGS = 1;
- public static final int TASK_ENCODING = 2;
-
- /**
- * The resize paint
- */
- private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
- private final VideoEditor mVideoEditor;
- /*
- * Semaphore to control preview calls
- */
- private final Semaphore mLock;
-
- private EditSettings mStoryBoardSettings;
-
- private String mOutputFilename;
-
- private PreviewClipProperties mClipProperties = null;
-
- private EditSettings mPreviewEditSettings;
-
- private AudioSettings mAudioSettings = null;
-
- private AudioTrack mAudioTrack = null;
-
- private boolean mInvalidatePreviewArray = true;
-
- private boolean mRegenerateAudio = true;
-
- private String mExportFilename = null;
- private int mExportVideoCodec = 0;
- private int mExportAudioCodec = 0;
- private int mProgressToApp;
-
- private String mRenderPreviewOverlayFile;
- private int mRenderPreviewRenderingMode;
-
- private boolean mIsFirstProgress;
-
- private static final String AUDIO_TRACK_PCM_FILE = "AudioPcm.pcm";
-
- // Processing indication
- public static final int PROCESSING_NONE = 0;
- public static final int PROCESSING_AUDIO_PCM = 1;
- public static final int PROCESSING_TRANSITION = 2;
- public static final int PROCESSING_KENBURNS = 3;
- public static final int PROCESSING_INTERMEDIATE1 = 11;
- public static final int PROCESSING_INTERMEDIATE2 = 12;
- public static final int PROCESSING_INTERMEDIATE3 = 13;
- public static final int PROCESSING_EXPORT = 20;
-
- private int mProcessingState;
- private Object mProcessingObject;
- private PreviewProgressListener mPreviewProgressListener;
- private ExportProgressListener mExportProgressListener;
- private ExtractAudioWaveformProgressListener mExtractAudioWaveformProgressListener;
- private MediaProcessingProgressListener mMediaProcessingProgressListener;
- private final String mProjectPath;
-
- private long mPreviewProgress;
-
- private String mAudioTrackPCMFilePath;
-
- private int mTotalClips = 0;
-
- private boolean mErrorFlagSet = false;
-
- @SuppressWarnings("unused")
- private long mManualEditContext;
-
- /* Listeners */
-
- /**
- * Interface definition for a listener to be invoked when there is an update
- * in a running task.
- */
- public interface OnProgressUpdateListener {
- /**
- * Called when there is an update.
- *
- * @param taskId id of the task reporting an update.
- * @param progress progress of the task [0..100].
- * @see BasicEdit#TASK_ENCODING
- */
- public void OnProgressUpdate(int taskId, int progress);
- }
-
- /** Defines the version. */
- public final class Version {
-
- /** Major version number */
- public int major;
-
- /** Minor version number */
- public int minor;
-
- /** Revision number */
- public int revision;
-
- /** VIDEOEDITOR major version number */
- private static final int VIDEOEDITOR_MAJOR_VERSION = 0;
-
- /** VIDEOEDITOR minor version number */
- private static final int VIDEOEDITOR_MINOR_VERSION = 0;
-
- /** VIDEOEDITOR revision number */
- private static final int VIDEOEDITOR_REVISION_VERSION = 1;
-
- /** Method which returns the current VIDEOEDITOR version */
- public Version getVersion() {
- Version version = new Version();
-
- version.major = Version.VIDEOEDITOR_MAJOR_VERSION;
- version.minor = Version.VIDEOEDITOR_MINOR_VERSION;
- version.revision = Version.VIDEOEDITOR_REVISION_VERSION;
-
- return version;
- }
- }
-
- /**
- * Defines output audio formats.
- */
- public final class AudioFormat {
- /** No audio present in output clip. Used to generate video only clip */
- public static final int NO_AUDIO = 0;
-
- /** AMR Narrow Band. */
- public static final int AMR_NB = 1;
-
- /** Advanced Audio Coding (AAC). */
- public static final int AAC = 2;
-
- /** Advanced Audio Codec Plus (HE-AAC v1). */
- public static final int AAC_PLUS = 3;
-
- /** Advanced Audio Codec Plus (HE-AAC v2). */
- public static final int ENHANCED_AAC_PLUS = 4;
-
- /** MPEG layer 3 (MP3). */
- public static final int MP3 = 5;
-
- /** Enhanced Variable RateCodec (EVRC). */
- public static final int EVRC = 6;
-
- /** PCM (PCM). */
- public static final int PCM = 7;
-
- /** No transcoding. Output audio format is same as input audio format */
- public static final int NULL_AUDIO = 254;
-
- /** Unsupported audio format. */
- public static final int UNSUPPORTED_AUDIO = 255;
- }
-
- /**
- * Defines audio sampling frequencies.
- */
- public final class AudioSamplingFrequency {
- /**
- * Default sampling frequency. Uses the default frequency for a specific
- * audio format. For AAC the only supported (and thus default) sampling
- * frequency is 16 kHz. For this audio format the sampling frequency in
- * the OutputParams.
- **/
- public static final int FREQ_DEFAULT = 0;
-
- /** Audio sampling frequency of 8000 Hz. */
- public static final int FREQ_8000 = 8000;
-
- /** Audio sampling frequency of 11025 Hz. */
- public static final int FREQ_11025 = 11025;
-
- /** Audio sampling frequency of 12000 Hz. */
- public static final int FREQ_12000 = 12000;
-
- /** Audio sampling frequency of 16000 Hz. */
- public static final int FREQ_16000 = 16000;
-
- /** Audio sampling frequency of 22050 Hz. */
- public static final int FREQ_22050 = 22050;
-
- /** Audio sampling frequency of 24000 Hz. */
- public static final int FREQ_24000 = 24000;
-
- /** Audio sampling frequency of 32000 Hz. */
- public static final int FREQ_32000 = 32000;
-
- /** Audio sampling frequency of 44100 Hz. */
- public static final int FREQ_44100 = 44100;
-
- /** Audio sampling frequency of 48000 Hz. Not available for output file. */
- public static final int FREQ_48000 = 48000;
- }
-
- /**
- * Defines the supported fixed audio and video bitrates. These values are
- * for output audio video only.
- */
- public final class Bitrate {
- /** Variable bitrate. Means no bitrate regulation */
- public static final int VARIABLE = -1;
-
- /** An undefined bitrate. */
- public static final int UNDEFINED = 0;
-
- /** A bitrate of 9.2 kbits/s. */
- public static final int BR_9_2_KBPS = 9200;
-
- /** A bitrate of 12.2 kbits/s. */
- public static final int BR_12_2_KBPS = 12200;
-
- /** A bitrate of 16 kbits/s. */
- public static final int BR_16_KBPS = 16000;
-
- /** A bitrate of 24 kbits/s. */
- public static final int BR_24_KBPS = 24000;
-
- /** A bitrate of 32 kbits/s. */
- public static final int BR_32_KBPS = 32000;
-
- /** A bitrate of 48 kbits/s. */
- public static final int BR_48_KBPS = 48000;
-
- /** A bitrate of 64 kbits/s. */
- public static final int BR_64_KBPS = 64000;
-
- /** A bitrate of 96 kbits/s. */
- public static final int BR_96_KBPS = 96000;
-
- /** A bitrate of 128 kbits/s. */
- public static final int BR_128_KBPS = 128000;
-
- /** A bitrate of 192 kbits/s. */
- public static final int BR_192_KBPS = 192000;
-
- /** A bitrate of 256 kbits/s. */
- public static final int BR_256_KBPS = 256000;
-
- /** A bitrate of 288 kbits/s. */
- public static final int BR_288_KBPS = 288000;
-
- /** A bitrate of 384 kbits/s. */
- public static final int BR_384_KBPS = 384000;
-
- /** A bitrate of 512 kbits/s. */
- public static final int BR_512_KBPS = 512000;
-
- /** A bitrate of 800 kbits/s. */
- public static final int BR_800_KBPS = 800000;
-
- /** A bitrate of 2 Mbits/s. */
- public static final int BR_2_MBPS = 2000000;
-
- /** A bitrate of 5 Mbits/s. */
- public static final int BR_5_MBPS = 5000000;
-
- /** A bitrate of 8 Mbits/s. */
- public static final int BR_8_MBPS = 8000000;
- }
-
- /**
- * Defines all supported file types.
- */
- public final class FileType {
- /** 3GPP file type. */
- public static final int THREE_GPP = 0;
-
- /** MP4 file type. */
- public static final int MP4 = 1;
-
- /** AMR file type. */
- public static final int AMR = 2;
-
- /** MP3 audio file type. */
- public static final int MP3 = 3;
-
- /** PCM audio file type. */
- public static final int PCM = 4;
-
- /** JPEG image file type. */
- public static final int JPG = 5;
-
- /** GIF image file type. */
- public static final int GIF = 7;
-
- /** PNG image file type. */
- public static final int PNG = 8;
-
- /** M4V file type. */
- public static final int M4V = 10;
-
- /** Unsupported file type. */
- public static final int UNSUPPORTED = 255;
- }
-
- /**
- * Defines rendering types. Rendering can only be applied to files
- * containing video streams.
- **/
- public final class MediaRendering {
- /**
- * Resize to fit the output video with changing the aspect ratio if
- * needed.
- */
- public static final int RESIZING = 0;
-
- /**
- * Crop the input video to fit it with the output video resolution.
- **/
- public static final int CROPPING = 1;
-
- /**
- * Resize to fit the output video resolution but maintain the aspect
- * ratio. This framing type adds black borders if needed.
- */
- public static final int BLACK_BORDERS = 2;
- }
-
- /**
- * Defines the results.
- */
- public final class Result {
- /** No error. result OK */
- public static final int NO_ERROR = 0;
-
- /** File not found */
- public static final int ERR_FILE_NOT_FOUND = 1;
-
- /**
- * In case of UTF8 conversion, the size of the converted path will be
- * more than the corresponding allocated buffer.
- */
- public static final int ERR_BUFFER_OUT_TOO_SMALL = 2;
-
- /** Invalid file type. */
- public static final int ERR_INVALID_FILE_TYPE = 3;
-
- /** Invalid effect kind. */
- public static final int ERR_INVALID_EFFECT_KIND = 4;
-
- /** Invalid video effect. */
- public static final int ERR_INVALID_VIDEO_EFFECT_TYPE = 5;
-
- /** Invalid audio effect. */
- public static final int ERR_INVALID_AUDIO_EFFECT_TYPE = 6;
-
- /** Invalid video transition. */
- public static final int ERR_INVALID_VIDEO_TRANSITION_TYPE = 7;
-
- /** Invalid audio transition. */
- public static final int ERR_INVALID_AUDIO_TRANSITION_TYPE = 8;
-
- /** Invalid encoding frame rate. */
- public static final int ERR_INVALID_VIDEO_ENCODING_FRAME_RATE = 9;
-
- /** External effect is called but this function is not set. */
- public static final int ERR_EXTERNAL_EFFECT_NULL = 10;
-
- /** External transition is called but this function is not set. */
- public static final int ERR_EXTERNAL_TRANSITION_NULL = 11;
-
- /** Begin time cut is larger than the video clip duration. */
- public static final int ERR_BEGIN_CUT_LARGER_THAN_DURATION = 12;
-
- /** Begin cut time is larger or equal than end cut. */
- public static final int ERR_BEGIN_CUT_LARGER_THAN_END_CUT = 13;
-
- /** Two consecutive transitions are overlapping on one clip. */
- public static final int ERR_OVERLAPPING_TRANSITIONS = 14;
-
- /** Internal error, type size mismatch. */
- public static final int ERR_ANALYSIS_DATA_SIZE_TOO_SMALL = 15;
-
- /** An input 3GPP file is invalid/corrupted. */
- public static final int ERR_INVALID_3GPP_FILE = 16;
-
- /** A file contains an unsupported video format. */
- public static final int ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT = 17;
-
- /** A file contains an unsupported audio format. */
- public static final int ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT = 18;
-
- /** A file format is not supported. */
- public static final int ERR_AMR_EDITING_UNSUPPORTED = 19;
-
- /** An input clip has an unexpectedly large Video AU. */
- public static final int ERR_INPUT_VIDEO_AU_TOO_LARGE = 20;
-
- /** An input clip has an unexpectedly large Audio AU. */
- public static final int ERR_INPUT_AUDIO_AU_TOO_LARGE = 21;
-
- /** An input clip has a corrupted Audio AU. */
- public static final int ERR_INPUT_AUDIO_CORRUPTED_AU = 22;
-
- /** The video encoder encountered an Access Unit error. */
- public static final int ERR_ENCODER_ACCES_UNIT_ERROR = 23;
-
- /** Unsupported video format for Video Editing. */
- public static final int ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT = 24;
-
- /** Unsupported H263 profile for Video Editing. */
- public static final int ERR_EDITING_UNSUPPORTED_H263_PROFILE = 25;
-
- /** Unsupported MPEG-4 profile for Video Editing. */
- public static final int ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE = 26;
-
- /** Unsupported MPEG-4 RVLC tool for Video Editing. */
- public static final int ERR_EDITING_UNSUPPORTED_MPEG4_RVLC = 27;
-
- /** Unsupported audio format for Video Editing. */
- public static final int ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT = 28;
-
- /** File contains no supported stream. */
- public static final int ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE = 29;
-
- /** File contains no video stream or an unsupported video stream. */
- public static final int ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 30;
-
- /** Internal error, clip analysis version mismatch. */
- public static final int ERR_INVALID_CLIP_ANALYSIS_VERSION = 31;
-
- /**
- * At least one of the clip analysis has been generated on another
- * platform (WIN32, ARM, etc.).
- */
- public static final int ERR_INVALID_CLIP_ANALYSIS_PLATFORM = 32;
-
- /** Clips don't have the same video format (H263 or MPEG4). */
- public static final int ERR_INCOMPATIBLE_VIDEO_FORMAT = 33;
-
- /** Clips don't have the same frame size. */
- public static final int ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE = 34;
-
- /** Clips don't have the same MPEG-4 time scale. */
- public static final int ERR_INCOMPATIBLE_VIDEO_TIME_SCALE = 35;
-
- /** Clips don't have the same use of MPEG-4 data partitioning. */
- public static final int ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING = 36;
-
- /** MP3 clips can't be assembled. */
- public static final int ERR_UNSUPPORTED_MP3_ASSEMBLY = 37;
-
- /**
- * The input 3GPP file does not contain any supported audio or video
- * track.
- */
- public static final int ERR_NO_SUPPORTED_STREAM_IN_FILE = 38;
-
- /**
- * The Volume of the added audio track (AddVolume) must be strictly
- * superior than zero.
- */
- public static final int ERR_ADDVOLUME_EQUALS_ZERO = 39;
-
- /**
- * The time at which an audio track is added can't be higher than the
- * input video track duration..
- */
- public static final int ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION = 40;
-
- /** The audio track file format setting is undefined. */
- public static final int ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT = 41;
-
- /** The added audio track stream has an unsupported format. */
- public static final int ERR_UNSUPPORTED_ADDED_AUDIO_STREAM = 42;
-
- /** The audio mixing feature doesn't support the audio track type. */
- public static final int ERR_AUDIO_MIXING_UNSUPPORTED = 43;
-
- /** The audio mixing feature doesn't support MP3 audio tracks. */
- public static final int ERR_AUDIO_MIXING_MP3_UNSUPPORTED = 44;
-
- /**
- * An added audio track limits the available features: uiAddCts must be
- * 0 and bRemoveOriginal must be true.
- */
- public static final int ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK = 45;
-
- /**
- * An added audio track limits the available features: uiAddCts must be
- * 0 and bRemoveOriginal must be true.
- */
- public static final int ERR_FEATURE_UNSUPPORTED_WITH_AAC = 46;
-
- /** Input audio track is not of a type that can be mixed with output. */
- public static final int ERR_AUDIO_CANNOT_BE_MIXED = 47;
-
- /** Input audio track is not AMR-NB, so it can't be mixed with output. */
- public static final int ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED = 48;
-
- /**
- * An added EVRC audio track limit the available features: uiAddCts must
- * be 0 and bRemoveOriginal must be true.
- */
- public static final int ERR_FEATURE_UNSUPPORTED_WITH_EVRC = 49;
-
- /** H263 profiles other than 0 are not supported. */
- public static final int ERR_H263_PROFILE_NOT_SUPPORTED = 51;
-
- /** File contains no video stream or an unsupported video stream. */
- public static final int ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 52;
-
- /** Transcoding of the input file(s) is necessary. */
- public static final int WAR_TRANSCODING_NECESSARY = 53;
-
- /**
- * The size of the output file will exceed the maximum configured value.
- */
- public static final int WAR_MAX_OUTPUT_SIZE_EXCEEDED = 54;
-
- /** The time scale is too big. */
- public static final int WAR_TIMESCALE_TOO_BIG = 55;
-
- /** The year is out of range */
- public static final int ERR_CLOCK_BAD_REF_YEAR = 56;
-
- /** The directory could not be opened */
- public static final int ERR_DIR_OPEN_FAILED = 57;
-
- /** The directory could not be read */
- public static final int ERR_DIR_READ_FAILED = 58;
-
- /** There are no more entries in the current directory */
- public static final int ERR_DIR_NO_MORE_ENTRY = 59;
-
- /** The input parameter/s has error */
- public static final int ERR_PARAMETER = 60;
-
- /** There is a state machine error */
- public static final int ERR_STATE = 61;
-
- /** Memory allocation failed */
- public static final int ERR_ALLOC = 62;
-
- /** Context is invalid */
- public static final int ERR_BAD_CONTEXT = 63;
-
- /** Context creation failed */
- public static final int ERR_CONTEXT_FAILED = 64;
-
- /** Invalid stream ID */
- public static final int ERR_BAD_STREAM_ID = 65;
-
- /** Invalid option ID */
- public static final int ERR_BAD_OPTION_ID = 66;
-
- /** The option is write only */
- public static final int ERR_WRITE_ONLY = 67;
-
- /** The option is read only */
- public static final int ERR_READ_ONLY = 68;
-
- /** The feature is not implemented in this version */
- public static final int ERR_NOT_IMPLEMENTED = 69;
-
- /** The media type is not supported */
- public static final int ERR_UNSUPPORTED_MEDIA_TYPE = 70;
-
- /** No data to be encoded */
- public static final int WAR_NO_DATA_YET = 71;
-
- /** No data to be decoded */
- public static final int WAR_NO_MORE_STREAM = 72;
-
- /** Time stamp is invalid */
- public static final int WAR_INVALID_TIME = 73;
-
- /** No more data to be decoded */
- public static final int WAR_NO_MORE_AU = 74;
-
- /** Semaphore timed out */
- public static final int WAR_TIME_OUT = 75;
-
- /** Memory buffer is full */
- public static final int WAR_BUFFER_FULL = 76;
-
- /** Server has asked for redirection */
- public static final int WAR_REDIRECT = 77;
-
- /** Too many streams in input */
- public static final int WAR_TOO_MUCH_STREAMS = 78;
-
- /** The file cannot be opened/ written into as it is locked */
- public static final int ERR_FILE_LOCKED = 79;
-
- /** The file access mode is invalid */
- public static final int ERR_FILE_BAD_MODE_ACCESS = 80;
-
- /** The file pointer points to an invalid location */
- public static final int ERR_FILE_INVALID_POSITION = 81;
-
- /** Invalid string */
- public static final int ERR_STR_BAD_STRING = 94;
-
- /** The input string cannot be converted */
- public static final int ERR_STR_CONV_FAILED = 95;
-
- /** The string size is too large */
- public static final int ERR_STR_OVERFLOW = 96;
-
- /** Bad string arguments */
- public static final int ERR_STR_BAD_ARGS = 97;
-
- /** The string value is larger than maximum size allowed */
- public static final int WAR_STR_OVERFLOW = 98;
-
- /** The string value is not present in this comparison operation */
- public static final int WAR_STR_NOT_FOUND = 99;
-
- /** The thread is not started */
- public static final int ERR_THREAD_NOT_STARTED = 100;
-
- /** Trancoding done warning */
- public static final int WAR_TRANSCODING_DONE = 101;
-
- /** Unsupported mediatype */
- public static final int WAR_MEDIATYPE_NOT_SUPPORTED = 102;
-
- /** Input file contains invalid/unsupported streams */
- public static final int ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM = 103;
-
- /** Invalid input file */
- public static final int ERR_INVALID_INPUT_FILE = 104;
-
- /** Invalid output video format */
- public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT = 105;
-
- /** Invalid output video frame size */
- public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE = 106;
-
- /** Invalid output video frame rate */
- public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE = 107;
-
- /** Invalid output audio format */
- public static final int ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT = 108;
-
- /** Invalid video frame size for H.263 */
- public static final int ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263 = 109;
-
- /** Invalid video frame rate for H.263 */
- public static final int ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263 = 110;
-
- /** invalid playback duration */
- public static final int ERR_DURATION_IS_NULL = 111;
-
- /** Invalid H.263 profile in file */
- public static final int ERR_H263_FORBIDDEN_IN_MP4_FILE = 112;
-
- /** Invalid AAC sampling frequency */
- public static final int ERR_INVALID_AAC_SAMPLING_FREQUENCY = 113;
-
- /** Audio conversion failure */
- public static final int ERR_AUDIO_CONVERSION_FAILED = 114;
-
- /** Invalid trim start and end times */
- public static final int ERR_BEGIN_CUT_EQUALS_END_CUT = 115;
-
- /** End time smaller than start time for trim */
- public static final int ERR_END_CUT_SMALLER_THAN_BEGIN_CUT = 116;
-
- /** Output file size is small */
- public static final int ERR_MAXFILESIZE_TOO_SMALL = 117;
-
- /** Output video bitrate is too low */
- public static final int ERR_VIDEOBITRATE_TOO_LOW = 118;
-
- /** Output audio bitrate is too low */
- public static final int ERR_AUDIOBITRATE_TOO_LOW = 119;
-
- /** Output video bitrate is too high */
- public static final int ERR_VIDEOBITRATE_TOO_HIGH = 120;
-
- /** Output audio bitrate is too high */
- public static final int ERR_AUDIOBITRATE_TOO_HIGH = 121;
-
- /** Output file size is too small */
- public static final int ERR_OUTPUT_FILE_SIZE_TOO_SMALL = 122;
-
- /** Unknown stream type */
- public static final int ERR_READER_UNKNOWN_STREAM_TYPE = 123;
-
- /** Invalid metadata in input stream */
- public static final int WAR_READER_NO_METADATA = 124;
-
- /** Invalid file reader info warning */
- public static final int WAR_READER_INFORMATION_NOT_PRESENT = 125;
-
- /** Warning to indicate the the writer is being stopped */
- public static final int WAR_WRITER_STOP_REQ = 131;
-
- /** Video decoder failed to provide frame for transcoding */
- public static final int WAR_VIDEORENDERER_NO_NEW_FRAME = 132;
-
- /** Video deblocking filter is not implemented */
- public static final int WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED = 133;
-
- /** H.263 decoder profile not supported */
- public static final int ERR_DECODER_H263_PROFILE_NOT_SUPPORTED = 134;
-
- /** The input file contains unsupported H.263 profile */
- public static final int ERR_DECODER_H263_NOT_BASELINE = 135;
-
- /** There is no more space to store the output file */
- public static final int ERR_NOMORE_SPACE_FOR_FILE = 136;
-
- /** Internal error. */
- public static final int ERR_INTERNAL = 255;
- }
-
- /**
- * Defines output video formats.
- */
- public final class VideoFormat {
- /** No video present in output clip. Used to generate audio only clip */
- public static final int NO_VIDEO = 0;
-
- /** H263 video format. */
- public static final int H263 = 1;
-
- /** H264 video */
- public static final int H264 = 2;
-
- /** MPEG4 video format. */
- public static final int MPEG4 = 3;
-
- /** No transcoding. Output video format is same as input video format */
- public static final int NULL_VIDEO = 254;
-
- /** Unsupported video format. */
- public static final int UNSUPPORTED = 255;
- }
-
- /** Defines video frame sizes. */
- public final class VideoFrameSize {
-
- public static final int SIZE_UNDEFINED = -1;
-
- /** SQCIF 128 x 96 pixels. */
- public static final int SQCIF = 0;
-
- /** QQVGA 160 x 120 pixels. */
- public static final int QQVGA = 1;
-
- /** QCIF 176 x 144 pixels. */
- public static final int QCIF = 2;
-
- /** QVGA 320 x 240 pixels. */
- public static final int QVGA = 3;
-
- /** CIF 352 x 288 pixels. */
- public static final int CIF = 4;
-
- /** VGA 640 x 480 pixels. */
- public static final int VGA = 5;
-
- /** WVGA 800 X 480 pixels */
- public static final int WVGA = 6;
-
- /** NTSC 720 X 480 pixels */
- public static final int NTSC = 7;
-
- /** 640 x 360 */
- public static final int nHD = 8;
-
- /** 854 x 480 */
- public static final int WVGA16x9 = 9;
-
- /** 720p 1280 X 720 */
- public static final int V720p = 10;
-
- /** W720p 1080 x 720 */
- public static final int W720p = 11;
-
- /** S720p 960 x 720 */
- public static final int S720p = 12;
-
- /** 1080p 1920 x 1080 */
- public static final int V1080p = 13;
- }
-
- /**
- * Defines output video frame rates.
- */
- public final class VideoFrameRate {
- /** Frame rate of 5 frames per second. */
- public static final int FR_5_FPS = 0;
-
- /** Frame rate of 7.5 frames per second. */
- public static final int FR_7_5_FPS = 1;
-
- /** Frame rate of 10 frames per second. */
- public static final int FR_10_FPS = 2;
-
- /** Frame rate of 12.5 frames per second. */
- public static final int FR_12_5_FPS = 3;
-
- /** Frame rate of 15 frames per second. */
- public static final int FR_15_FPS = 4;
-
- /** Frame rate of 20 frames per second. */
- public static final int FR_20_FPS = 5;
-
- /** Frame rate of 25 frames per second. */
- public static final int FR_25_FPS = 6;
-
- /** Frame rate of 30 frames per second. */
- public static final int FR_30_FPS = 7;
- }
-
- /**
- * Defines Video Effect Types.
- */
- public static class VideoEffect {
-
- public static final int NONE = 0;
-
- public static final int FADE_FROM_BLACK = 8;
-
- public static final int FADE_TO_BLACK = 16;
-
- public static final int EXTERNAL = 256;
-
- public static final int BLACK_AND_WHITE = 257;
-
- public static final int PINK = 258;
-
- public static final int GREEN = 259;
-
- public static final int SEPIA = 260;
-
- public static final int NEGATIVE = 261;
-
- public static final int FRAMING = 262;
-
- public static final int TEXT = 263;
-
- public static final int ZOOM_IN = 264;
-
- public static final int ZOOM_OUT = 265;
-
- public static final int FIFTIES = 266;
-
- public static final int COLORRGB16 = 267;
-
- public static final int GRADIENT = 268;
- }
-
- /**
- * Defines the video transitions.
- */
- public static class VideoTransition {
- /** No transition */
- public static final int NONE = 0;
-
- /** Cross fade transition */
- public static final int CROSS_FADE = 1;
-
- /** External transition. Currently not available. */
- public static final int EXTERNAL = 256;
-
- /** AlphaMagic transition. */
- public static final int ALPHA_MAGIC = 257;
-
- /** Slide transition. */
- public static final int SLIDE_TRANSITION = 258;
-
- /** Fade to black transition. */
- public static final int FADE_BLACK = 259;
- }
-
- /**
- * Defines settings for the AlphaMagic transition
- */
- public static class AlphaMagicSettings {
- /** Name of the alpha file (JPEG file). */
- public String file;
-
- /** Blending percentage [0..100] 0 = no blending. */
- public int blendingPercent;
-
- /** Invert the default rotation direction of the AlphaMagic effect. */
- public boolean invertRotation;
-
- public int rgbWidth;
- public int rgbHeight;
- }
-
- /** Defines the direction of the Slide transition. */
- public static final class SlideDirection {
-
- /** Right out left in. */
- public static final int RIGHT_OUT_LEFT_IN = 0;
-
- /** Left out right in. */
- public static final int LEFT_OUT_RIGTH_IN = 1;
-
- /** Top out bottom in. */
- public static final int TOP_OUT_BOTTOM_IN = 2;
-
- /** Bottom out top in */
- public static final int BOTTOM_OUT_TOP_IN = 3;
- }
-
- /** Defines the Slide transition settings. */
- public static class SlideTransitionSettings {
- /**
- * Direction of the slide transition. See {@link SlideDirection
- * SlideDirection} for valid values.
- */
- public int direction;
- }
-
- /**
- * Defines the settings of a single clip.
- */
- public static class ClipSettings {
-
- /**
- * The path to the clip file.
- * <p>
- * File format of the clip, it can be:
- * <ul>
- * <li>3GP file containing MPEG4/H263/H264 video and AAC/AMR audio
- * <li>JPG file
- * </ul>
- */
-
- public String clipPath;
-
- /**
- * The path of the decoded file. This is used only for image files.
- */
- public String clipDecodedPath;
-
- /**
- * The path of the Original file. This is used only for image files.
- */
- public String clipOriginalPath;
-
- /**
- * File type of the clip. See {@link FileType FileType} for valid
- * values.
- */
- public int fileType;
-
- /** Begin of the cut in the clip in milliseconds. */
- public int beginCutTime;
-
- /**
- * End of the cut in the clip in milliseconds. Set both
- * <code>beginCutTime</code> and <code>endCutTime</code> to
- * <code>0</code> to get the full length of the clip without a cut. In
- * case of JPG clip, this is the duration of the JPEG file.
- */
- public int endCutTime;
-
- /**
- * Begin of the cut in the clip in percentage of the file duration.
- */
- public int beginCutPercent;
-
- /**
- * End of the cut in the clip in percentage of the file duration. Set
- * both <code>beginCutPercent</code> and <code>endCutPercent</code> to
- * <code>0</code> to get the full length of the clip without a cut.
- */
- public int endCutPercent;
-
- /** Enable panning and zooming. */
- public boolean panZoomEnabled;
-
- /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
- public int panZoomPercentStart;
-
- /** Top left X coordinate at start of clip. */
- public int panZoomTopLeftXStart;
-
- /** Top left Y coordinate at start of clip. */
- public int panZoomTopLeftYStart;
-
- /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
- public int panZoomPercentEnd;
-
- /** Top left X coordinate at end of clip. */
- public int panZoomTopLeftXEnd;
-
- /** Top left Y coordinate at end of clip. */
- public int panZoomTopLeftYEnd;
-
- /**
- * Set The media rendering. See {@link MediaRendering MediaRendering}
- * for valid values.
- */
- public int mediaRendering;
-
- /**
- * RGB width and Height
- */
- public int rgbWidth;
- public int rgbHeight;
- /**
- * Video rotation degree.
- */
- public int rotationDegree;
- }
-
- /**
- * Defines settings for a transition.
- */
- public static class TransitionSettings {
-
- /** Duration of the transition in msec. */
- public int duration;
-
- /**
- * Transition type for video. See {@link VideoTransition
- * VideoTransition} for valid values.
- */
- public int videoTransitionType;
-
- /**
- * Transition type for audio. See {@link AudioTransition
- * AudioTransition} for valid values.
- */
- public int audioTransitionType;
-
- /**
- * Transition behaviour. See {@link TransitionBehaviour
- * TransitionBehaviour} for valid values.
- */
- public int transitionBehaviour;
-
- /**
- * Settings for AlphaMagic transition. Only needs to be set if
- * <code>videoTransitionType</code> is set to
- * <code>VideoTransition.ALPHA_MAGIC</code>. See
- * {@link AlphaMagicSettings AlphaMagicSettings}.
- */
- public AlphaMagicSettings alphaSettings;
-
- /**
- * Settings for the Slide transition. See
- * {@link SlideTransitionSettings SlideTransitionSettings}.
- */
- public SlideTransitionSettings slideSettings;
- }
-
- public static final class AudioTransition {
- /** No audio transition. */
- public static final int NONE = 0;
-
- /** Cross-fade audio transition. */
- public static final int CROSS_FADE = 1;
- }
-
- /**
- * Defines transition behaviors.
- */
- public static final class TransitionBehaviour {
-
- /** The transition uses an increasing speed. */
- public static final int SPEED_UP = 0;
-
- /** The transition uses a linear (constant) speed. */
- public static final int LINEAR = 1;
-
- /** The transition uses a decreasing speed. */
- public static final int SPEED_DOWN = 2;
-
- /**
- * The transition uses a constant speed, but slows down in the middle
- * section.
- */
- public static final int SLOW_MIDDLE = 3;
-
- /**
- * The transition uses a constant speed, but increases speed in the
- * middle section.
- */
- public static final int FAST_MIDDLE = 4;
- }
-
- /**
- * Defines settings for the background music.
- */
- public static class BackgroundMusicSettings {
-
- /** Background music file. */
- public String file;
-
- /** File type. See {@link FileType FileType} for valid values. */
- public int fileType;
-
- /**
- * Insertion time in milliseconds, in the output video where the
- * background music must be inserted.
- */
- public long insertionTime;
-
- /**
- * Volume, as a percentage of the background music track, to use. If
- * this field is set to 100, the background music will replace the audio
- * from the video input file(s).
- */
- public int volumePercent;
-
- /**
- * Start time in milliseconds in the background muisc file from where
- * the background music should loop. Set both <code>beginLoop</code> and
- * <code>endLoop</code> to <code>0</code> to disable looping.
- */
- public long beginLoop;
-
- /**
- * End time in milliseconds in the background music file to where the
- * background music should loop. Set both <code>beginLoop</code> and
- * <code>endLoop</code> to <code>0</code> to disable looping.
- */
- public long endLoop;
-
- public boolean enableDucking;
-
- public int duckingThreshold;
-
- public int lowVolume;
-
- public boolean isLooping;
- }
-
- /** Defines settings for an effect. */
- public static class AudioEffect {
- /** No audio effect. */
- public static final int NONE = 0;
-
- /** Fade-in effect. */
- public static final int FADE_IN = 8;
-
- /** Fade-out effect. */
- public static final int FADE_OUT = 16;
- }
-
- /** Defines the effect settings. */
- public static class EffectSettings {
-
- /** Start time of the effect in milliseconds. */
- public int startTime;
-
- /** Duration of the effect in milliseconds. */
- public int duration;
-
- /**
- * Video effect type. See {@link VideoEffect VideoEffect} for valid
- * values.
- */
- public int videoEffectType;
-
- /**
- * Audio effect type. See {@link AudioEffect AudioEffect} for valid
- * values.
- */
- public int audioEffectType;
-
- /**
- * Start time of the effect in percents of the duration of the clip. A
- * value of 0 percent means start time is from the beginning of the
- * clip.
- */
- public int startPercent;
-
- /**
- * Duration of the effect in percents of the duration of the clip.
- */
- public int durationPercent;
-
- /**
- * Framing file.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
- * this field is ignored.
- */
- public String framingFile;
-
- /**
- * Framing buffer.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
- * this field is ignored.
- */
- public int[] framingBuffer;
-
- /**
- * Bitmap type Can be from RGB_565 (4), ARGB_4444 (5), ARGB_8888 (6);
- **/
-
- public int bitmapType;
-
- public int width;
-
- public int height;
-
- /**
- * Top left x coordinate. This coordinate is used to set the x
- * coordinate of the picture in the framing file when the framing file
- * is selected. The x coordinate is also used to set the location of the
- * text in the text effect.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
- * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
- * ignored.
- */
- public int topLeftX;
-
- /**
- * Top left y coordinate. This coordinate is used to set the y
- * coordinate of the picture in the framing file when the framing file
- * is selected. The y coordinate is also used to set the location of the
- * text in the text effect.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
- * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
- * ignored.
- */
- public int topLeftY;
-
- /**
- * Should the frame be resized or not. If this field is set to
- * <link>true</code> then the frame size is matched with the output
- * video size.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
- * this field is ignored.
- */
- public boolean framingResize;
-
- /**
- * Size to which the framing buffer needs to be resized to
- * This is valid only if framingResize is true
- */
- public int framingScaledSize;
- /**
- * Text to insert in the video.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
- * field is ignored.
- */
- public String text;
-
- /**
- * Text attributes for the text to insert in the video.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
- * field is ignored. For more details about this field see the
- * integration guide.
- */
- public String textRenderingData;
-
- /** Width of the text buffer in pixels. */
- public int textBufferWidth;
-
- /** Height of the text buffer in pixels. */
- public int textBufferHeight;
-
- /**
- * Processing rate for the fifties effect. A high value (e.g. 30)
- * results in high effect strength.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#FIFTIES VideoEffect.FIFTIES}. Otherwise
- * this field is ignored.
- */
- public int fiftiesFrameRate;
-
- /**
- * RGB 16 color of the RGB16 and gradient color effect.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#COLORRGB16 VideoEffect.COLORRGB16} or
- * {@link VideoEffect#GRADIENT VideoEffect.GRADIENT}. Otherwise this
- * field is ignored.
- */
- public int rgb16InputColor;
-
- /**
- * Start alpha blending percentage.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
- * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
- * is ignored.
- */
- public int alphaBlendingStartPercent;
-
- /**
- * Middle alpha blending percentage.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
- * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
- * is ignored.
- */
- public int alphaBlendingMiddlePercent;
-
- /**
- * End alpha blending percentage.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
- * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
- * is ignored.
- */
- public int alphaBlendingEndPercent;
-
- /**
- * Duration, in percentage of effect duration of the fade-in phase.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
- * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
- * is ignored.
- */
- public int alphaBlendingFadeInTimePercent;
-
- /**
- * Duration, in percentage of effect duration of the fade-out phase.
- * <p>
- * This field is only used when the field <code>videoEffectType</code>
- * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
- * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
- * is ignored.
- */
- public int alphaBlendingFadeOutTimePercent;
- }
-
- /** Defines the clip properties for preview */
- public static class PreviewClips {
-
- /**
- * The path to the clip file.
- * <p>
- * File format of the clip, it can be:
- * <ul>
- * <li>3GP file containing MPEG4/H263 video and AAC/AMR audio
- * <li>JPG file
- * </ul>
- */
-
- public String clipPath;
-
- /**
- * File type of the clip. See {@link FileType FileType} for valid
- * values.
- */
- public int fileType;
-
- /** Begin of the cut in the clip in milliseconds. */
- public long beginPlayTime;
-
- public long endPlayTime;
-
- /**
- * Set The media rendering. See {@link MediaRendering MediaRendering}
- * for valid values.
- */
- public int mediaRendering;
-
- }
-
- /** Defines the audio settings. */
- public static class AudioSettings {
-
- String pFile;
-
- /** < PCM file path */
- String Id;
-
- boolean bRemoveOriginal;
-
- /** < If true, the original audio track is not taken into account */
- int channels;
-
- /** < Number of channels (1=mono, 2=stereo) of BGM clip */
- int Fs;
-
- /**
- * < Sampling audio frequency (8000 for amr, 16000 or more for aac) of
- * BGM clip
- */
- int ExtendedFs;
-
- /** < Extended frequency for AAC+, eAAC+ streams of BGM clip */
- long startMs;
-
- /** < Time, in milliseconds, at which the added audio track is inserted */
- long beginCutTime;
-
- long endCutTime;
-
- int fileType;
-
- int volume;
-
- /** < Volume, in percentage, of the added audio track */
- boolean loop;
-
- /** < Looping on/off > **/
-
- /** Audio mix and Duck **/
- int ducking_threshold;
-
- int ducking_lowVolume;
-
- boolean bInDucking_enable;
-
- String pcmFilePath;
- }
-
- /** Encapsulates preview clips and effect settings */
- public static class PreviewSettings {
-
- public PreviewClips[] previewClipsArray;
-
- /** The effect settings. */
- public EffectSettings[] effectSettingsArray;
-
- }
-
- /** Encapsulates clip properties */
- public static class PreviewClipProperties {
-
- public Properties[] clipProperties;
-
- }
-
- /** Defines the editing settings. */
- public static class EditSettings {
-
- /**
- * Array of clip settings. There is one <code>clipSetting</code> for
- * each clip.
- */
- public ClipSettings[] clipSettingsArray;
-
- /**
- * Array of transition settings. If there are n clips (and thus n
- * <code>clipSettings</code>) then there are (n-1) transitions and (n-1)
- * <code>transistionSettings</code> in
- * <code>transistionSettingsArray</code>.
- */
- public TransitionSettings[] transitionSettingsArray;
-
- /** The effect settings. */
- public EffectSettings[] effectSettingsArray;
-
- /**
- * Video frame rate of the output clip. See {@link VideoFrameRate
- * VideoFrameRate} for valid values.
- */
- public int videoFrameRate;
-
- /** Output file name. Must be an absolute path. */
- public String outputFile;
-
- /**
- * Size of the video frames in the output clip. See
- * {@link VideoFrameSize VideoFrameSize} for valid values.
- */
- public int videoFrameSize;
-
- /**
- * Format of the video stream in the output clip. See
- * {@link VideoFormat VideoFormat} for valid values.
- */
- public int videoFormat;
-
- /**
- * Profile of the video stream in the output clip.
- */
- public int videoProfile;
-
- /**
- * Level of the video stream in the output clip.
- */
- public int videoLevel;
-
- /**
- * Format of the audio stream in the output clip. See
- * {@link AudioFormat AudioFormat} for valid values.
- */
- public int audioFormat;
-
- /**
- * Sampling frequency of the audio stream in the output clip. See
- * {@link AudioSamplingFrequency AudioSamplingFrequency} for valid
- * values.
- */
- public int audioSamplingFreq;
-
- /**
- * Maximum file size. By setting this you can set the maximum size of
- * the output clip. Set it to <code>0</code> to let the class ignore
- * this filed.
- */
- public int maxFileSize;
-
- /**
- * Number of audio channels in output clip. Use <code>0</code> for none,
- * <code>1</code> for mono or <code>2</code> for stereo. None is only
- * allowed when the <code>audioFormat</code> field is set to
- * {@link AudioFormat#NO_AUDIO AudioFormat.NO_AUDIO} or
- * {@link AudioFormat#NULL_AUDIO AudioFormat.NULL_AUDIO} Mono is only
- * allowed when the <code>audioFormat</code> field is set to
- * {@link AudioFormat#AAC AudioFormat.AAC}
- */
- public int audioChannels;
-
- /** Video bitrate. See {@link Bitrate Bitrate} for valid values. */
- public int videoBitrate;
-
- /** Audio bitrate. See {@link Bitrate Bitrate} for valid values. */
- public int audioBitrate;
-
- /**
- * Background music settings. See {@link BackgroundMusicSettings
- * BackgroundMusicSettings} for valid values.
- */
- public BackgroundMusicSettings backgroundMusicSettings;
-
- public int primaryTrackVolume;
-
- }
-
- /**
- * Defines the media properties.
- **/
-
- public static class Properties {
-
- /**
- * Duration of the media in milliseconds.
- */
-
- public int duration;
-
- /**
- * File type.
- */
-
- public int fileType;
-
- /**
- * Video format.
- */
-
- public int videoFormat;
-
- /**
- * Duration of the video stream of the media in milliseconds.
- */
-
- public int videoDuration;
-
- /**
- * Bitrate of the video stream of the media.
- */
-
- public int videoBitrate;
-
- /**
- * Width of the video frames or the width of the still picture in
- * pixels.
- */
-
- public int width;
-
- /**
- * Height of the video frames or the height of the still picture in
- * pixels.
- */
-
- public int height;
-
- /**
- * Average frame rate of video in the media in frames per second.
- */
-
- public float averageFrameRate;
-
- /**
- * Profile of the video in the media.
- */
-
- public int profile;
-
- /**
- * Level of the video in the media.
- */
-
- public int level;
-
- /**
- * Is Video Profile supported.
- */
-
- public boolean profileSupported;
-
- /**
- * Is Video Level supported.
- */
-
- public boolean levelSupported;
-
- /**
- * Audio format.
- */
-
- public int audioFormat;
-
- /**
- * Duration of the audio stream of the media in milliseconds.
- */
-
- public int audioDuration;
-
- /**
- * Bitrate of the audio stream of the media.
- */
-
- public int audioBitrate;
-
- /**
- * Number of audio channels in the media.
- */
-
- public int audioChannels;
-
- /**
- * Sampling frequency of the audio stream in the media in samples per
- * second.
- */
-
- public int audioSamplingFrequency;
-
- /**
- * Volume value of the audio track as percentage.
- */
- public int audioVolumeValue;
-
- /**
- * Video rotation degree.
- */
- public int videoRotation;
-
- public String Id;
- }
-
- /**
- * Constructor
- *
- * @param projectPath The path where the VideoEditor stores all files
- * related to the project
- * @param lock The semaphore
- * @param veObj The video editor reference
- */
- public MediaArtistNativeHelper(String projectPath, Semaphore lock, VideoEditor veObj) {
- mProjectPath = projectPath;
- if (veObj != null) {
- mVideoEditor = veObj;
- } else {
- mVideoEditor = null;
- throw new IllegalArgumentException("video editor object is null");
- }
- if (mStoryBoardSettings == null) {
- mStoryBoardSettings = new EditSettings();
- }
-
- mLock = lock;
-
- _init(mProjectPath, "null");
- mAudioTrackPCMFilePath = null;
- }
-
- /**
- * @return The project path
- */
- String getProjectPath() {
- return mProjectPath;
- }
-
- /**
- * @return The Audio Track PCM file path
- */
- String getProjectAudioTrackPCMFilePath() {
- return mAudioTrackPCMFilePath;
- }
-
- /**
- * Invalidates the PCM file
- */
- void invalidatePcmFile() {
- if (mAudioTrackPCMFilePath != null) {
- new File(mAudioTrackPCMFilePath).delete();
- mAudioTrackPCMFilePath = null;
- }
- }
-
- @SuppressWarnings("unused")
- private void onProgressUpdate(int taskId, int progress) {
- if (mProcessingState == PROCESSING_EXPORT) {
- if (mExportProgressListener != null) {
- if (mProgressToApp < progress) {
- mExportProgressListener.onProgress(mVideoEditor, mOutputFilename, progress);
- /* record previous progress */
- mProgressToApp = progress;
- }
- }
- }
- else {
- // Adapt progress depending on current state
- int actualProgress = 0;
- int action = 0;
-
- if (mProcessingState == PROCESSING_AUDIO_PCM) {
- action = MediaProcessingProgressListener.ACTION_DECODE;
- } else {
- action = MediaProcessingProgressListener.ACTION_ENCODE;
- }
-
- switch (mProcessingState) {
- case PROCESSING_AUDIO_PCM:
- actualProgress = progress;
- break;
- case PROCESSING_TRANSITION:
- actualProgress = progress;
- break;
- case PROCESSING_KENBURNS:
- actualProgress = progress;
- break;
- case PROCESSING_INTERMEDIATE1:
- if ((progress == 0) && (mProgressToApp != 0)) {
- mProgressToApp = 0;
- }
- if ((progress != 0) || (mProgressToApp != 0)) {
- actualProgress = progress/4;
- }
- break;
- case PROCESSING_INTERMEDIATE2:
- if ((progress != 0) || (mProgressToApp != 0)) {
- actualProgress = 25 + progress/4;
- }
- break;
- case PROCESSING_INTERMEDIATE3:
- if ((progress != 0) || (mProgressToApp != 0)) {
- actualProgress = 50 + progress/2;
- }
- break;
- case PROCESSING_NONE:
-
- default:
- Log.e(TAG, "ERROR unexpected State=" + mProcessingState);
- return;
- }
- if ((mProgressToApp != actualProgress) && (actualProgress != 0)) {
-
- mProgressToApp = actualProgress;
-
- if (mMediaProcessingProgressListener != null) {
- // Send the progress indication
- mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
- actualProgress);
- }
- }
- /* avoid 0 in next intermediate call */
- if (mProgressToApp == 0) {
- if (mMediaProcessingProgressListener != null) {
- /*
- * Send the progress indication
- */
- mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
- actualProgress);
- }
- mProgressToApp = 1;
- }
- }
- }
-
- @SuppressWarnings("unused")
- private void onPreviewProgressUpdate(int progress, boolean isFinished,
- boolean updateOverlay, String filename, int renderingMode, int error) {
- if (mPreviewProgressListener != null) {
- if (mIsFirstProgress) {
- mPreviewProgressListener.onStart(mVideoEditor);
- mIsFirstProgress = false;
- }
-
- final VideoEditor.OverlayData overlayData;
- if (updateOverlay) {
- overlayData = new VideoEditor.OverlayData();
- if (filename != null) {
- overlayData.set(BitmapFactory.decodeFile(filename), renderingMode);
- } else {
- overlayData.setClear();
- }
- } else {
- overlayData = null;
- }
-
- if (progress != 0) {
- mPreviewProgress = progress;
- }
-
- if (isFinished) {
- mPreviewProgressListener.onStop(mVideoEditor);
- } else if (error != 0) {
- mPreviewProgressListener.onError(mVideoEditor, error);
- } else {
- mPreviewProgressListener.onProgress(mVideoEditor, progress, overlayData);
- }
- }
- }
-
- /**
- * Release the native helper object
- */
- void releaseNativeHelper() throws InterruptedException {
- release();
- }
-
- /**
- * Release the native helper to end the Audio Graph process
- */
- @SuppressWarnings("unused")
- private void onAudioGraphExtractProgressUpdate(int progress, boolean isVideo) {
- if ((mExtractAudioWaveformProgressListener != null) && (progress > 0)) {
- mExtractAudioWaveformProgressListener.onProgress(progress);
- }
- }
-
- /**
- * Populates the Effect Settings in EffectSettings
- *
- * @param effects The reference of EffectColor
- *
- * @return The populated effect settings in EffectSettings reference
- */
- EffectSettings getEffectSettings(EffectColor effects) {
- EffectSettings effectSettings = new EffectSettings();
- effectSettings.startTime = (int)effects.getStartTime();
- effectSettings.duration = (int)effects.getDuration();
- effectSettings.videoEffectType = getEffectColorType(effects);
- effectSettings.audioEffectType = 0;
- effectSettings.startPercent = 0;
- effectSettings.durationPercent = 0;
- effectSettings.framingFile = null;
- effectSettings.topLeftX = 0;
- effectSettings.topLeftY = 0;
- effectSettings.framingResize = false;
- effectSettings.text = null;
- effectSettings.textRenderingData = null;
- effectSettings.textBufferWidth = 0;
- effectSettings.textBufferHeight = 0;
- if (effects.getType() == EffectColor.TYPE_FIFTIES) {
- effectSettings.fiftiesFrameRate = 15;
- } else {
- effectSettings.fiftiesFrameRate = 0;
- }
-
- if ((effectSettings.videoEffectType == VideoEffect.COLORRGB16)
- || (effectSettings.videoEffectType == VideoEffect.GRADIENT)) {
- effectSettings.rgb16InputColor = effects.getColor();
- }
-
- effectSettings.alphaBlendingStartPercent = 0;
- effectSettings.alphaBlendingMiddlePercent = 0;
- effectSettings.alphaBlendingEndPercent = 0;
- effectSettings.alphaBlendingFadeInTimePercent = 0;
- effectSettings.alphaBlendingFadeOutTimePercent = 0;
- return effectSettings;
- }
-
- /**
- * Populates the Overlay Settings in EffectSettings
- *
- * @param overlay The reference of OverlayFrame
- *
- * @return The populated overlay settings in EffectSettings reference
- */
- EffectSettings getOverlaySettings(OverlayFrame overlay) {
- EffectSettings effectSettings = new EffectSettings();
- Bitmap bitmap = null;
-
- effectSettings.startTime = (int)overlay.getStartTime();
- effectSettings.duration = (int)overlay.getDuration();
- effectSettings.videoEffectType = VideoEffect.FRAMING;
- effectSettings.audioEffectType = 0;
- effectSettings.startPercent = 0;
- effectSettings.durationPercent = 0;
- effectSettings.framingFile = null;
-
- if ((bitmap = overlay.getBitmap()) != null) {
- effectSettings.framingFile = overlay.getFilename();
-
- if (effectSettings.framingFile == null) {
- try {
- (overlay).save(mProjectPath);
- } catch (IOException e) {
- Log.e(TAG, "getOverlaySettings : File not found");
- }
- effectSettings.framingFile = overlay.getFilename();
- }
- if (bitmap.getConfig() == Bitmap.Config.ARGB_8888)
- effectSettings.bitmapType = 6;
- else if (bitmap.getConfig() == Bitmap.Config.ARGB_4444)
- effectSettings.bitmapType = 5;
- else if (bitmap.getConfig() == Bitmap.Config.RGB_565)
- effectSettings.bitmapType = 4;
- else if (bitmap.getConfig() == Bitmap.Config.ALPHA_8)
- throw new RuntimeException("Bitmap config not supported");
-
- effectSettings.width = bitmap.getWidth();
- effectSettings.height = bitmap.getHeight();
- effectSettings.framingBuffer = new int[effectSettings.width];
- int tmp = 0;
- short maxAlpha = 0;
- short minAlpha = (short)0xFF;
- short alpha = 0;
- while (tmp < effectSettings.height) {
- bitmap.getPixels(effectSettings.framingBuffer, 0,
- effectSettings.width, 0, tmp,
- effectSettings.width, 1);
- for (int i = 0; i < effectSettings.width; i++) {
- alpha = (short)((effectSettings.framingBuffer[i] >> 24) & 0xFF);
- if (alpha > maxAlpha) {
- maxAlpha = alpha;
- }
- if (alpha < minAlpha) {
- minAlpha = alpha;
- }
- }
- tmp += 1;
- }
- alpha = (short)((maxAlpha + minAlpha) / 2);
- alpha = (short)((alpha * 100) / 256);
- effectSettings.alphaBlendingEndPercent = alpha;
- effectSettings.alphaBlendingMiddlePercent = alpha;
- effectSettings.alphaBlendingStartPercent = alpha;
- effectSettings.alphaBlendingFadeInTimePercent = 100;
- effectSettings.alphaBlendingFadeOutTimePercent = 100;
- effectSettings.framingBuffer = null;
-
- /*
- * Set the resized RGB file dimensions
- */
- effectSettings.width = overlay.getResizedRGBSizeWidth();
- if(effectSettings.width == 0) {
- effectSettings.width = bitmap.getWidth();
- }
-
- effectSettings.height = overlay.getResizedRGBSizeHeight();
- if(effectSettings.height == 0) {
- effectSettings.height = bitmap.getHeight();
- }
-
- }
-
- effectSettings.topLeftX = 0;
- effectSettings.topLeftY = 0;
-
- effectSettings.framingResize = true;
- effectSettings.text = null;
- effectSettings.textRenderingData = null;
- effectSettings.textBufferWidth = 0;
- effectSettings.textBufferHeight = 0;
- effectSettings.fiftiesFrameRate = 0;
- effectSettings.rgb16InputColor = 0;
- int mediaItemHeight;
- int aspectRatio;
- if (overlay.getMediaItem() instanceof MediaImageItem) {
- if (((MediaImageItem)overlay.getMediaItem()).getGeneratedImageClip() != null) {
- // Ken Burns was applied
- mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipHeight();
- aspectRatio = getAspectRatio(
- ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipWidth()
- , mediaItemHeight);
- } else {
- //For image get the scaled height. Aspect ratio would remain the same
- mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getScaledHeight();
- aspectRatio = overlay.getMediaItem().getAspectRatio();
- }
- } else {
- aspectRatio = overlay.getMediaItem().getAspectRatio();
- mediaItemHeight = overlay.getMediaItem().getHeight();
- }
- effectSettings.framingScaledSize = findVideoResolution(aspectRatio, mediaItemHeight);
- return effectSettings;
- }
-
- /* get Video Editor aspect ratio */
- int nativeHelperGetAspectRatio() {
- return mVideoEditor.getAspectRatio();
- }
-
- /**
- * Sets the export audio codec
- *
- * @param export audio codec
- *
- */
- void setAudioCodec(int codec) {
- mExportAudioCodec = codec;
- }
- /**
- * Sets the export video codec
- *
- * @param export video codec
- *
- */
- void setVideoCodec(int codec) {
- mExportVideoCodec = codec;
- }
-
- /**
- * Sets the audio regenerate flag
- *
- * @param flag The boolean to set the audio regenerate flag
- *
- */
- void setAudioflag(boolean flag) {
- //check if the file exists.
- if (!(new File(String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE)).exists())) {
- flag = true;
- }
- mRegenerateAudio = flag;
- }
-
- /**
- * Gets the audio regenerate flag
- *
- * @param return The boolean to get the audio regenerate flag
- *
- */
- boolean getAudioflag() {
- return mRegenerateAudio;
- }
-
- /**
- * Maps the average frame rate to one of the defined enum values
- *
- * @param averageFrameRate The average frame rate of video item
- *
- * @return The frame rate from one of the defined enum values
- */
- int GetClosestVideoFrameRate(int averageFrameRate) {
- if (averageFrameRate >= 25) {
- return VideoFrameRate.FR_30_FPS;
- } else if (averageFrameRate >= 20) {
- return VideoFrameRate.FR_25_FPS;
- } else if (averageFrameRate >= 15) {
- return VideoFrameRate.FR_20_FPS;
- } else if (averageFrameRate >= 12) {
- return VideoFrameRate.FR_15_FPS;
- } else if (averageFrameRate >= 10) {
- return VideoFrameRate.FR_12_5_FPS;
- } else if (averageFrameRate >= 7) {
- return VideoFrameRate.FR_10_FPS;
- } else if (averageFrameRate >= 5) {
- return VideoFrameRate.FR_7_5_FPS;
- } else {
- return -1;
- }
- }
-
- /**
- * Helper function to adjust the effect or overlay start time
- * depending on the begin and end boundary time of meddia item
- */
- public void adjustEffectsStartTimeAndDuration(EffectSettings lEffect, int beginCutTime,
- int endCutTime) {
-
- int effectStartTime = 0;
- int effectDuration = 0;
-
- /**
- * cbct -> clip begin cut time
- * cect -> clip end cut time
- ****************************************
- * | |
- * | cbct cect |
- * | <-1--> | | |
- * | <--|-2-> | |
- * | | <---3---> | |
- * | | <--|-4---> |
- * | | | <--5--> |
- * | <---|------6----|----> |
- * | |
- * < : effectStart
- * > : effectStart + effectDuration
- ****************************************
- **/
-
- /** 1 & 5 */
- /**
- * Effect falls out side the trim duration. In such a case effects shall
- * not be applied.
- */
- if ((lEffect.startTime > endCutTime)
- || ((lEffect.startTime + lEffect.duration) <= beginCutTime)) {
-
- effectStartTime = 0;
- effectDuration = 0;
-
- lEffect.startTime = effectStartTime;
- lEffect.duration = effectDuration;
- return;
- }
-
- /** 2 */
- if ((lEffect.startTime < beginCutTime)
- && ((lEffect.startTime + lEffect.duration) > beginCutTime)
- && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
- effectStartTime = 0;
- effectDuration = lEffect.duration;
-
- effectDuration -= (beginCutTime - lEffect.startTime);
- lEffect.startTime = effectStartTime;
- lEffect.duration = effectDuration;
- return;
- }
-
- /** 3 */
- if ((lEffect.startTime >= beginCutTime)
- && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
- effectStartTime = lEffect.startTime - beginCutTime;
- lEffect.startTime = effectStartTime;
- lEffect.duration = lEffect.duration;
- return;
- }
-
- /** 4 */
- if ((lEffect.startTime >= beginCutTime)
- && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
- effectStartTime = lEffect.startTime - beginCutTime;
- effectDuration = endCutTime - lEffect.startTime;
- lEffect.startTime = effectStartTime;
- lEffect.duration = effectDuration;
- return;
- }
-
- /** 6 */
- if ((lEffect.startTime < beginCutTime)
- && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
- effectStartTime = 0;
- effectDuration = endCutTime - beginCutTime;
- lEffect.startTime = effectStartTime;
- lEffect.duration = effectDuration;
- return;
- }
-
- }
-
- /**
- * Generates the clip for preview or export
- *
- * @param editSettings The EditSettings reference for generating
- * a clip for preview or export
- *
- * @return error value
- */
- public int generateClip(EditSettings editSettings) {
- int err = 0;
-
- try {
- err = nativeGenerateClip(editSettings);
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal Argument exception in load settings");
- return -1;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in load settings");
- return -1;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in load settings");
- return -1;
- }
- return err;
- }
-
- /**
- * Init function to initialiZe the ClipSettings reference to
- * default values
- *
- * @param lclipSettings The ClipSettings reference
- */
- void initClipSettings(ClipSettings lclipSettings) {
- lclipSettings.clipPath = null;
- lclipSettings.clipDecodedPath = null;
- lclipSettings.clipOriginalPath = null;
- lclipSettings.fileType = 0;
- lclipSettings.endCutTime = 0;
- lclipSettings.beginCutTime = 0;
- lclipSettings.beginCutPercent = 0;
- lclipSettings.endCutPercent = 0;
- lclipSettings.panZoomEnabled = false;
- lclipSettings.panZoomPercentStart = 0;
- lclipSettings.panZoomTopLeftXStart = 0;
- lclipSettings.panZoomTopLeftYStart = 0;
- lclipSettings.panZoomPercentEnd = 0;
- lclipSettings.panZoomTopLeftXEnd = 0;
- lclipSettings.panZoomTopLeftYEnd = 0;
- lclipSettings.mediaRendering = 0;
- lclipSettings.rotationDegree = 0;
- }
-
-
- /**
- * Populates the settings for generating an effect clip
- *
- * @param lMediaItem The media item for which the effect clip
- * needs to be generated
- * @param lclipSettings The ClipSettings reference containing
- * clips data
- * @param e The EditSettings reference containing effect specific data
- * @param uniqueId The unique id used in the name of the output clip
- * @param clipNo Used for internal purpose
- *
- * @return The name and path of generated clip
- */
- String generateEffectClip(MediaItem lMediaItem, ClipSettings lclipSettings,
- EditSettings e,String uniqueId,int clipNo) {
- int err = 0;
- EditSettings editSettings = null;
- String EffectClipPath = null;
- int outVideoProfile = 0;
- int outVideoLevel = 0;
- editSettings = new EditSettings();
-
- editSettings.clipSettingsArray = new ClipSettings[1];
- editSettings.clipSettingsArray[0] = lclipSettings;
-
- editSettings.backgroundMusicSettings = null;
- editSettings.transitionSettingsArray = null;
- editSettings.effectSettingsArray = e.effectSettingsArray;
-
- EffectClipPath = String.format(mProjectPath + "/" + "ClipEffectIntermediate" + "_"
- + lMediaItem.getId() + uniqueId + ".3gp");
-
- File tmpFile = new File(EffectClipPath);
- if (tmpFile.exists()) {
- tmpFile.delete();
- }
-
- outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
- outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
- editSettings.videoProfile = outVideoProfile;
- editSettings.videoLevel= outVideoLevel;
-
- if (lMediaItem instanceof MediaVideoItem) {
- MediaVideoItem m = (MediaVideoItem)lMediaItem;
-
- editSettings.audioFormat = AudioFormat.AAC;
- editSettings.audioChannels = 2;
- editSettings.audioBitrate = Bitrate.BR_64_KBPS;
- editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
- editSettings.videoFormat = VideoFormat.H264;
- editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
- editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
- m.getHeight());
- editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
- } else {
- MediaImageItem m = (MediaImageItem)lMediaItem;
- editSettings.audioBitrate = Bitrate.BR_64_KBPS;
- editSettings.audioChannels = 2;
- editSettings.audioFormat = AudioFormat.AAC;
- editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
- editSettings.videoFormat = VideoFormat.H264;
- editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
- editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
- m.getScaledHeight());
- editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
- }
-
- editSettings.outputFile = EffectClipPath;
-
- if (clipNo == 1) {
- mProcessingState = PROCESSING_INTERMEDIATE1;
- } else if (clipNo == 2) {
- mProcessingState = PROCESSING_INTERMEDIATE2;
- }
- mProcessingObject = lMediaItem;
- err = generateClip(editSettings);
- mProcessingState = PROCESSING_NONE;
-
- if (err == 0) {
- lclipSettings.clipPath = EffectClipPath;
- lclipSettings.fileType = FileType.THREE_GPP;
- return EffectClipPath;
- } else {
- throw new RuntimeException("preview generation cannot be completed");
- }
- }
-
-
- /**
- * Populates the settings for generating a Ken Burn effect clip
- *
- * @param m The media image item for which the Ken Burn effect clip
- * needs to be generated
- * @param e The EditSettings reference clip specific data
- *
- * @return The name and path of generated clip
- */
- String generateKenBurnsClip(EditSettings e, MediaImageItem m) {
- String output = null;
- int err = 0;
- int outVideoProfile = 0;
- int outVideoLevel = 0;
-
- e.backgroundMusicSettings = null;
- e.transitionSettingsArray = null;
- e.effectSettingsArray = null;
- output = String.format(mProjectPath + "/" + "ImageClip-" + m.getId() + ".3gp");
-
- File tmpFile = new File(output);
- if (tmpFile.exists()) {
- tmpFile.delete();
- }
-
- outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
- outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
- e.videoProfile = outVideoProfile;
- e.videoLevel = outVideoLevel;
-
- e.outputFile = output;
- e.audioBitrate = Bitrate.BR_64_KBPS;
- e.audioChannels = 2;
- e.audioFormat = AudioFormat.AAC;
- e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
- e.videoFormat = VideoFormat.H264;
- e.videoFrameRate = VideoFrameRate.FR_30_FPS;
- e.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
- m.getScaledHeight());
- e.videoBitrate = findVideoBitrate(e.videoFrameSize);
-
- mProcessingState = PROCESSING_KENBURNS;
- mProcessingObject = m;
- err = generateClip(e);
- // Reset the processing state and check for errors
- mProcessingState = PROCESSING_NONE;
- if (err != 0) {
- throw new RuntimeException("preview generation cannot be completed");
- }
- return output;
- }
-
-
- /**
- * Calculates the output resolution for transition clip
- *
- * @param m1 First media item associated with transition
- * @param m2 Second media item associated with transition
- *
- * @return The transition resolution
- */
- private int getTransitionResolution(MediaItem m1, MediaItem m2) {
- int clip1Height = 0;
- int clip2Height = 0;
- int videoSize = 0;
-
- if (m1 != null && m2 != null) {
- if (m1 instanceof MediaVideoItem) {
- clip1Height = m1.getHeight();
- } else if (m1 instanceof MediaImageItem) {
- clip1Height = ((MediaImageItem)m1).getScaledHeight();
- }
- if (m2 instanceof MediaVideoItem) {
- clip2Height = m2.getHeight();
- } else if (m2 instanceof MediaImageItem) {
- clip2Height = ((MediaImageItem)m2).getScaledHeight();
- }
- if (clip1Height > clip2Height) {
- videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
- } else {
- videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
- }
- } else if (m1 == null && m2 != null) {
- if (m2 instanceof MediaVideoItem) {
- clip2Height = m2.getHeight();
- } else if (m2 instanceof MediaImageItem) {
- clip2Height = ((MediaImageItem)m2).getScaledHeight();
- }
- videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
- } else if (m1 != null && m2 == null) {
- if (m1 instanceof MediaVideoItem) {
- clip1Height = m1.getHeight();
- } else if (m1 instanceof MediaImageItem) {
- clip1Height = ((MediaImageItem)m1).getScaledHeight();
- }
- videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
- }
- return videoSize;
- }
-
- /**
- * Populates the settings for generating an transition clip
- *
- * @param m1 First media item associated with transition
- * @param m2 Second media item associated with transition
- * @param e The EditSettings reference containing
- * clip specific data
- * @param uniqueId The unique id used in the name of the output clip
- * @param t The Transition specific data
- *
- * @return The name and path of generated clip
- */
- String generateTransitionClip(EditSettings e, String uniqueId,
- MediaItem m1, MediaItem m2,Transition t) {
- String outputFilename = null;
- int err = 0;
- int outVideoProfile = 0;
- int outVideoLevel = 0;
- outputFilename = String.format(mProjectPath + "/" + uniqueId + ".3gp");
-
- outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
- outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
- e.videoProfile = outVideoProfile;
- e.videoLevel = outVideoLevel;
-
- e.outputFile = outputFilename;
- e.audioBitrate = Bitrate.BR_64_KBPS;
- e.audioChannels = 2;
- e.audioFormat = AudioFormat.AAC;
- e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
- e.videoFormat = VideoFormat.H264;
- e.videoFrameRate = VideoFrameRate.FR_30_FPS;
- e.videoFrameSize = getTransitionResolution(m1, m2);
- e.videoBitrate = findVideoBitrate(e.videoFrameSize);
-
- if (new File(outputFilename).exists()) {
- new File(outputFilename).delete();
- }
- mProcessingState = PROCESSING_INTERMEDIATE3;
- mProcessingObject = t;
- err = generateClip(e);
- // Reset the processing state and check for errors
- mProcessingState = PROCESSING_NONE;
- if (err != 0) {
- throw new RuntimeException("preview generation cannot be completed");
- }
- return outputFilename;
- }
-
- /**
- * Populates effects and overlays in EffectSettings structure
- * and also adjust the start time and duration of effects and overlays
- * w.r.t to total story board time
- *
- * @param m1 Media item associated with effect
- * @param effectSettings The EffectSettings reference containing
- * effect specific data
- * @param beginCutTime The begin cut time of the clip associated with effect
- * @param endCutTime The end cut time of the clip associated with effect
- * @param storyBoardTime The current story board time
- *
- * @return The updated index
- */
- private int populateEffects(MediaItem m, EffectSettings[] effectSettings, int i,
- int beginCutTime, int endCutTime, int storyBoardTime) {
-
- if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
- && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
- beginCutTime += m.getBeginTransition().getDuration();
- endCutTime -= m.getEndTransition().getDuration();
- } else if (m.getBeginTransition() == null && m.getEndTransition() != null
- && m.getEndTransition().getDuration() > 0) {
- endCutTime -= m.getEndTransition().getDuration();
- } else if (m.getEndTransition() == null && m.getBeginTransition() != null
- && m.getBeginTransition().getDuration() > 0) {
- beginCutTime += m.getBeginTransition().getDuration();
- }
-
- final List<Effect> effects = m.getAllEffects();
- final List<Overlay> overlays = m.getAllOverlays();
-
- for (Overlay overlay : overlays) {
- effectSettings[i] = getOverlaySettings((OverlayFrame)overlay);
- adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
- effectSettings[i].startTime += storyBoardTime;
- i++;
- }
-
- for (Effect effect : effects) {
- if (effect instanceof EffectColor) {
- effectSettings[i] = getEffectSettings((EffectColor)effect);
- adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
- effectSettings[i].startTime += storyBoardTime;
- i++;
- }
- }
-
- return i;
- }
-
- /**
- * Adjusts the media item boundaries for use in export or preview
- *
- * @param clipSettings The ClipSettings reference
- * @param clipProperties The Properties reference
- * @param m The media item
- */
- private void adjustMediaItemBoundary(ClipSettings clipSettings,
- Properties clipProperties, MediaItem m) {
- if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
- && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
- clipSettings.beginCutTime += m.getBeginTransition().getDuration();
- clipSettings.endCutTime -= m.getEndTransition().getDuration();
- } else if (m.getBeginTransition() == null && m.getEndTransition() != null
- && m.getEndTransition().getDuration() > 0) {
- clipSettings.endCutTime -= m.getEndTransition().getDuration();
- } else if (m.getEndTransition() == null && m.getBeginTransition() != null
- && m.getBeginTransition().getDuration() > 0) {
- clipSettings.beginCutTime += m.getBeginTransition().getDuration();
- }
-
- clipProperties.duration = clipSettings.endCutTime - clipSettings.beginCutTime;
-
- if (clipProperties.videoDuration != 0) {
- clipProperties.videoDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
- }
-
- if (clipProperties.audioDuration != 0) {
- clipProperties.audioDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
- }
- }
-
- /**
- * Generates the transition if transition is present
- * and is in invalidated state
- *
- * @param transition The Transition reference
- * @param editSettings The EditSettings reference
- * @param clipPropertiesArray The clip Properties array
- * @param i The index in clip Properties array for current clip
- */
- private void generateTransition(Transition transition, EditSettings editSettings,
- PreviewClipProperties clipPropertiesArray, int index) {
- if (!(transition.isGenerated())) {
- transition.generate();
- }
- editSettings.clipSettingsArray[index] = new ClipSettings();
- editSettings.clipSettingsArray[index].clipPath = transition.getFilename();
- editSettings.clipSettingsArray[index].fileType = FileType.THREE_GPP;
- editSettings.clipSettingsArray[index].beginCutTime = 0;
- editSettings.clipSettingsArray[index].endCutTime = (int)transition.getDuration();
- editSettings.clipSettingsArray[index].mediaRendering = MediaRendering.BLACK_BORDERS;
-
- try {
- clipPropertiesArray.clipProperties[index] =
- getMediaProperties(transition.getFilename());
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
- }
-
- clipPropertiesArray.clipProperties[index].Id = null;
- clipPropertiesArray.clipProperties[index].audioVolumeValue = 100;
- clipPropertiesArray.clipProperties[index].duration = (int)transition.getDuration();
- if (clipPropertiesArray.clipProperties[index].videoDuration != 0) {
- clipPropertiesArray.clipProperties[index].videoDuration = (int)transition.getDuration();
- }
-
- if (clipPropertiesArray.clipProperties[index].audioDuration != 0) {
- clipPropertiesArray.clipProperties[index].audioDuration = (int)transition.getDuration();
- }
- }
-
- /**
- * Sets the volume for current media item in clip properties array
- *
- * @param m The media item
- * @param clipProperties The clip properties array reference
- * @param i The index in clip Properties array for current clip
- */
- private void adjustVolume(MediaItem m, PreviewClipProperties clipProperties,
- int index) {
- if (m instanceof MediaVideoItem) {
- final boolean videoMuted = ((MediaVideoItem)m).isMuted();
- if (videoMuted == false) {
- mClipProperties.clipProperties[index].audioVolumeValue =
- ((MediaVideoItem)m).getVolume();
- } else {
- mClipProperties.clipProperties[index].audioVolumeValue = 0;
- }
- } else if (m instanceof MediaImageItem) {
- mClipProperties.clipProperties[index].audioVolumeValue = 0;
- }
- }
-
- /**
- * Checks for odd size image width and height
- *
- * @param m The media item
- * @param clipProperties The clip properties array reference
- * @param i The index in clip Properties array for current clip
- */
- private void checkOddSizeImage(MediaItem m, PreviewClipProperties clipProperties, int index) {
- if (m instanceof MediaImageItem) {
- int width = mClipProperties.clipProperties[index].width;
- int height = mClipProperties.clipProperties[index].height;
-
- if ((width % 2) != 0) {
- width -= 1;
- }
- if ((height % 2) != 0) {
- height -= 1;
- }
- mClipProperties.clipProperties[index].width = width;
- mClipProperties.clipProperties[index].height = height;
- }
- }
-
- /**
- * Populates the media item properties and calculates the maximum
- * height among all the clips
- *
- * @param m The media item
- * @param i The index in clip Properties array for current clip
- * @param maxHeight The max height from the clip properties
- *
- * @return Updates the max height if current clip's height is greater
- * than all previous clips height
- */
- private int populateMediaItemProperties(MediaItem m, int index, int maxHeight) {
- mPreviewEditSettings.clipSettingsArray[index] = new ClipSettings();
- if (m instanceof MediaVideoItem) {
- mPreviewEditSettings.clipSettingsArray[index] =
- ((MediaVideoItem)m).getVideoClipProperties();
- if (((MediaVideoItem)m).getHeight() > maxHeight) {
- maxHeight = ((MediaVideoItem)m).getHeight();
- }
- } else if (m instanceof MediaImageItem) {
- mPreviewEditSettings.clipSettingsArray[index] =
- ((MediaImageItem)m).getImageClipProperties();
- if (((MediaImageItem)m).getScaledHeight() > maxHeight) {
- maxHeight = ((MediaImageItem)m).getScaledHeight();
- }
- }
- /** + Handle the image files here */
- if (mPreviewEditSettings.clipSettingsArray[index].fileType == FileType.JPG) {
- mPreviewEditSettings.clipSettingsArray[index].clipDecodedPath =
- ((MediaImageItem)m).getDecodedImageFileName();
-
- mPreviewEditSettings.clipSettingsArray[index].clipOriginalPath =
- mPreviewEditSettings.clipSettingsArray[index].clipPath;
- }
- return maxHeight;
- }
-
- /**
- * Populates the background music track properties
- *
- * @param mediaBGMList The background music list
- *
- */
- private void populateBackgroundMusicProperties(List<AudioTrack> mediaBGMList) {
-
- if (mediaBGMList.size() == 1) {
- mAudioTrack = mediaBGMList.get(0);
- } else {
- mAudioTrack = null;
- }
-
- if (mAudioTrack != null) {
- mAudioSettings = new AudioSettings();
- Properties mAudioProperties = new Properties();
- mAudioSettings.pFile = null;
- mAudioSettings.Id = mAudioTrack.getId();
- try {
- mAudioProperties = getMediaProperties(mAudioTrack.getFilename());
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
- }
- mAudioSettings.bRemoveOriginal = false;
- mAudioSettings.channels = mAudioProperties.audioChannels;
- mAudioSettings.Fs = mAudioProperties.audioSamplingFrequency;
- mAudioSettings.loop = mAudioTrack.isLooping();
- mAudioSettings.ExtendedFs = 0;
- mAudioSettings.pFile = mAudioTrack.getFilename();
- mAudioSettings.startMs = mAudioTrack.getStartTime();
- mAudioSettings.beginCutTime = mAudioTrack.getBoundaryBeginTime();
- mAudioSettings.endCutTime = mAudioTrack.getBoundaryEndTime();
- if (mAudioTrack.isMuted()) {
- mAudioSettings.volume = 0;
- } else {
- mAudioSettings.volume = mAudioTrack.getVolume();
- }
- mAudioSettings.fileType = mAudioProperties.fileType;
- mAudioSettings.ducking_lowVolume = mAudioTrack.getDuckedTrackVolume();
- mAudioSettings.ducking_threshold = mAudioTrack.getDuckingThreshhold();
- mAudioSettings.bInDucking_enable = mAudioTrack.isDuckingEnabled();
- mAudioTrackPCMFilePath = String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE);
- mAudioSettings.pcmFilePath = mAudioTrackPCMFilePath;
-
- mPreviewEditSettings.backgroundMusicSettings = new BackgroundMusicSettings();
- mPreviewEditSettings.backgroundMusicSettings.file = mAudioTrackPCMFilePath;
- mPreviewEditSettings.backgroundMusicSettings.fileType = mAudioProperties.fileType;
- mPreviewEditSettings.backgroundMusicSettings.insertionTime =
- mAudioTrack.getStartTime();
- mPreviewEditSettings.backgroundMusicSettings.volumePercent = mAudioTrack.getVolume();
- mPreviewEditSettings.backgroundMusicSettings.beginLoop =
- mAudioTrack.getBoundaryBeginTime();
- mPreviewEditSettings.backgroundMusicSettings.endLoop =
- mAudioTrack.getBoundaryEndTime();
- mPreviewEditSettings.backgroundMusicSettings.enableDucking =
- mAudioTrack.isDuckingEnabled();
- mPreviewEditSettings.backgroundMusicSettings.duckingThreshold =
- mAudioTrack.getDuckingThreshhold();
- mPreviewEditSettings.backgroundMusicSettings.lowVolume =
- mAudioTrack.getDuckedTrackVolume();
- mPreviewEditSettings.backgroundMusicSettings.isLooping = mAudioTrack.isLooping();
- mPreviewEditSettings.primaryTrackVolume = 100;
- mProcessingState = PROCESSING_AUDIO_PCM;
- mProcessingObject = mAudioTrack;
- } else {
- mAudioSettings = null;
- mPreviewEditSettings.backgroundMusicSettings = null;
- mAudioTrackPCMFilePath = null;
- }
- }
-
- /**
- * Calculates all the effects in all the media items
- * in media items list
- *
- * @param mediaItemsList The media item list
- *
- * @return The total number of effects
- *
- */
- private int getTotalEffects(List<MediaItem> mediaItemsList) {
- int totalEffects = 0;
- final Iterator<MediaItem> it = mediaItemsList.iterator();
- while (it.hasNext()) {
- final MediaItem t = it.next();
- totalEffects += t.getAllEffects().size();
- totalEffects += t.getAllOverlays().size();
- final Iterator<Effect> ef = t.getAllEffects().iterator();
- while (ef.hasNext()) {
- final Effect e = ef.next();
- if (e instanceof EffectKenBurns) {
- totalEffects--;
- }
- }
- }
- return totalEffects;
- }
-
- /**
- * This function is responsible for forming clip settings
- * array and clip properties array including transition clips
- * and effect settings for preview purpose or export.
- *
- *
- * @param mediaItemsList The media item list
- * @param mediaTransitionList The transitions list
- * @param mediaBGMList The background music list
- * @param listener The MediaProcessingProgressListener
- *
- */
- void previewStoryBoard(List<MediaItem> mediaItemsList,
- List<Transition> mediaTransitionList, List<AudioTrack> mediaBGMList,
- MediaProcessingProgressListener listener) {
- if (mInvalidatePreviewArray) {
- int previewIndex = 0;
- int totalEffects = 0;
- int storyBoardTime = 0;
- int maxHeight = 0;
- int beginCutTime = 0;
- int endCutTime = 0;
- int effectIndex = 0;
- Transition lTransition = null;
- MediaItem lMediaItem = null;
- mPreviewEditSettings = new EditSettings();
- mClipProperties = new PreviewClipProperties();
- mTotalClips = 0;
-
- mTotalClips = mediaItemsList.size();
- for (Transition transition : mediaTransitionList) {
- if (transition.getDuration() > 0) {
- mTotalClips++;
- }
- }
-
- totalEffects = getTotalEffects(mediaItemsList);
-
- mPreviewEditSettings.clipSettingsArray = new ClipSettings[mTotalClips];
- mPreviewEditSettings.effectSettingsArray = new EffectSettings[totalEffects];
- mClipProperties.clipProperties = new Properties[mTotalClips];
-
- /** record the call back progress listener */
- mMediaProcessingProgressListener = listener;
- mProgressToApp = 0;
-
- if (mediaItemsList.size() > 0) {
- for (int i = 0; i < mediaItemsList.size(); i++) {
- /* Get the Media Item from the list */
- lMediaItem = mediaItemsList.get(i);
- if (lMediaItem instanceof MediaVideoItem) {
- beginCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryBeginTime();
- endCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryEndTime();
- } else if (lMediaItem instanceof MediaImageItem) {
- beginCutTime = 0;
- endCutTime = (int)((MediaImageItem)lMediaItem).getTimelineDuration();
- }
- /* Get the transition associated with Media Item */
- lTransition = lMediaItem.getBeginTransition();
- if (lTransition != null && (lTransition.getDuration() > 0)) {
- /* generate transition clip */
- generateTransition(lTransition, mPreviewEditSettings,
- mClipProperties, previewIndex);
- storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
- previewIndex++;
- }
- /* Populate media item properties */
- maxHeight = populateMediaItemProperties(lMediaItem, previewIndex, maxHeight);
- /* Get the clip properties of the media item. */
- if (lMediaItem instanceof MediaImageItem) {
- int tmpCnt = 0;
- boolean bEffectKbPresent = false;
- final List<Effect> effectList = lMediaItem.getAllEffects();
- /**
- * Check if Ken Burns effect is present
- */
- while (tmpCnt < effectList.size()) {
- if (effectList.get(tmpCnt) instanceof EffectKenBurns) {
- bEffectKbPresent = true;
- break;
- }
- tmpCnt++;
- }
-
- if (bEffectKbPresent) {
- try {
- if(((MediaImageItem)lMediaItem).getGeneratedImageClip() != null) {
- mClipProperties.clipProperties[previewIndex]
- = getMediaProperties(((MediaImageItem)lMediaItem).
- getGeneratedImageClip());
- }
- else {
- mClipProperties.clipProperties[previewIndex]
- = getMediaProperties(((MediaImageItem)lMediaItem).
- getScaledImageFileName());
- mClipProperties.clipProperties[previewIndex].width =
- ((MediaImageItem)lMediaItem).getScaledWidth();
- mClipProperties.clipProperties[previewIndex].height =
- ((MediaImageItem)lMediaItem).getScaledHeight();
- }
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
- }
- } else {
- try {
- mClipProperties.clipProperties[previewIndex]
- = getMediaProperties(((MediaImageItem)lMediaItem).
- getScaledImageFileName());
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
- }
- mClipProperties.clipProperties[previewIndex].width =
- ((MediaImageItem)lMediaItem).getScaledWidth();
- mClipProperties.clipProperties[previewIndex].height =
- ((MediaImageItem)lMediaItem).getScaledHeight();
- }
- } else {
- try {
- mClipProperties.clipProperties[previewIndex]
- = getMediaProperties(lMediaItem.getFilename());
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found");
- }
- }
- mClipProperties.clipProperties[previewIndex].Id = lMediaItem.getId();
- checkOddSizeImage(lMediaItem, mClipProperties, previewIndex);
- adjustVolume(lMediaItem, mClipProperties, previewIndex);
-
- /*
- * Adjust media item start time and end time w.r.t to begin
- * and end transitions associated with media item
- */
-
- adjustMediaItemBoundary(mPreviewEditSettings.clipSettingsArray[previewIndex],
- mClipProperties.clipProperties[previewIndex], lMediaItem);
-
- /*
- * Get all the effects and overlays for that media item and
- * adjust start time and duration of effects
- */
-
- effectIndex = populateEffects(lMediaItem,
- mPreviewEditSettings.effectSettingsArray, effectIndex, beginCutTime,
- endCutTime, storyBoardTime);
- storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
- previewIndex++;
-
- /* Check if there is any end transition at last media item */
-
- if (i == (mediaItemsList.size() - 1)) {
- lTransition = lMediaItem.getEndTransition();
- if (lTransition != null && (lTransition.getDuration() > 0)) {
- generateTransition(lTransition, mPreviewEditSettings, mClipProperties,
- previewIndex);
- break;
- }
- }
- }
-
- if (!mErrorFlagSet) {
- mPreviewEditSettings.videoFrameSize = findVideoResolution(mVideoEditor
- .getAspectRatio(), maxHeight);
- populateBackgroundMusicProperties(mediaBGMList);
-
- /** call to native populate settings */
- try {
- nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal argument exception in nativePopulateSettings");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in nativePopulateSettings");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in nativePopulateSettings");
- throw ex;
- }
- mInvalidatePreviewArray = false;
- mProcessingState = PROCESSING_NONE;
- }
- }
- if (mErrorFlagSet) {
- mErrorFlagSet = false;
- throw new RuntimeException("preview generation cannot be completed");
- }
- }
- } /* END of previewStoryBoard */
-
- /**
- * This function is responsible for starting the preview
- *
- *
- * @param surface The surface on which preview has to be displayed
- * @param fromMs The time in ms from which preview has to be started
- * @param toMs The time in ms till preview has to be played
- * @param loop To loop the preview or not
- * @param callbackAfterFrameCount INdicated after how many frames
- * the callback is needed
- * @param listener The PreviewProgressListener
- */
- void doPreview(Surface surface, long fromMs, long toMs, boolean loop,
- int callbackAfterFrameCount, PreviewProgressListener listener) {
- mPreviewProgress = fromMs;
- mIsFirstProgress = true;
- mPreviewProgressListener = listener;
-
- if (!mInvalidatePreviewArray) {
- try {
- /** Modify the image files names to rgb image files. */
- for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
- clipCnt++) {
- if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
- }
- }
- nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
- nativeStartPreview(surface, fromMs, toMs, callbackAfterFrameCount, loop);
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal argument exception in nativeStartPreview");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in nativeStartPreview");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in nativeStartPreview");
- throw ex;
- }
- } else {
- throw new IllegalStateException("generatePreview is in progress");
- }
- }
-
- /**
- * This function is responsible for stopping the preview
- */
- long stopPreview() {
- return nativeStopPreview();
- }
-
- /**
- * This function is responsible for rendering a single frame
- * from the complete story board on the surface
- *
- * @param surface The surface on which frame has to be rendered
- * @param time The time in ms at which the frame has to be rendered
- * @param surfaceWidth The surface width
- * @param surfaceHeight The surface height
- * @param overlayData The overlay data
- *
- * @return The actual time from the story board at which the frame was extracted
- * and rendered
- */
- long renderPreviewFrame(Surface surface, long time, int surfaceWidth,
- int surfaceHeight, VideoEditor.OverlayData overlayData) {
- if (mInvalidatePreviewArray) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Call generate preview first");
- }
- throw new IllegalStateException("Call generate preview first");
- }
-
- long timeMs = 0;
- try {
- for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
- clipCnt++) {
- if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
- }
- }
-
- // Reset the render preview frame params that shall be set by native.
- mRenderPreviewOverlayFile = null;
- mRenderPreviewRenderingMode = MediaRendering.RESIZING;
-
- nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-
- timeMs = (long)nativeRenderPreviewFrame(surface, time, surfaceWidth, surfaceHeight);
-
- if (mRenderPreviewOverlayFile != null) {
- overlayData.set(BitmapFactory.decodeFile(mRenderPreviewOverlayFile),
- mRenderPreviewRenderingMode);
- } else {
- overlayData.setClear();
- }
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal Argument exception in nativeRenderPreviewFrame");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in nativeRenderPreviewFrame");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in nativeRenderPreviewFrame");
- throw ex;
- }
-
- return timeMs;
- }
-
- private void previewFrameEditInfo(String filename, int renderingMode) {
- mRenderPreviewOverlayFile = filename;
- mRenderPreviewRenderingMode = renderingMode;
- }
-
-
- /**
- * This function is responsible for rendering a single frame
- * from a single media item on the surface
- *
- * @param surface The surface on which frame has to be rendered
- * @param filepath The file path for which the frame needs to be displayed
- * @param time The time in ms at which the frame has to be rendered
- * @param framewidth The frame width
- * @param framewidth The frame height
- *
- * @return The actual time from media item at which the frame was extracted
- * and rendered
- */
- long renderMediaItemPreviewFrame(Surface surface, String filepath,
- long time, int framewidth, int frameheight) {
- long timeMs = 0;
- try {
- timeMs = (long)nativeRenderMediaItemPreviewFrame(surface, filepath, framewidth,
- frameheight, 0, 0, time);
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "Illegal Argument exception in renderMediaItemPreviewFrame");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in renderMediaItemPreviewFrame");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
- throw ex;
- }
-
- return timeMs;
- }
-
- /**
- * This function sets the flag to invalidate the preview array
- * and for generating the preview again
- */
- void setGeneratePreview(boolean isRequired) {
- boolean semAcquiredDone = false;
- try {
- lock();
- semAcquiredDone = true;
- mInvalidatePreviewArray = isRequired;
- } catch (InterruptedException ex) {
- Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
- } finally {
- if (semAcquiredDone) {
- unlock();
- }
- }
- }
-
- /**
- * @return Returns the current status of preview invalidation
- * flag
- */
- boolean getGeneratePreview() {
- return mInvalidatePreviewArray;
- }
-
- /**
- * Calculates the aspect ratio from widht and height
- *
- * @param w The width of media item
- * @param h The height of media item
- *
- * @return The calculated aspect ratio
- */
- int getAspectRatio(int w, int h) {
- double apRatio = (double)(w) / (double)(h);
- BigDecimal bd = new BigDecimal(apRatio);
- bd = bd.setScale(3, BigDecimal.ROUND_HALF_UP);
- apRatio = bd.doubleValue();
- int var = MediaProperties.ASPECT_RATIO_16_9;
- if (apRatio >= 1.7) {
- var = MediaProperties.ASPECT_RATIO_16_9;
- } else if (apRatio >= 1.6) {
- var = MediaProperties.ASPECT_RATIO_5_3;
- } else if (apRatio >= 1.5) {
- var = MediaProperties.ASPECT_RATIO_3_2;
- } else if (apRatio > 1.3) {
- var = MediaProperties.ASPECT_RATIO_4_3;
- } else if (apRatio >= 1.2) {
- var = MediaProperties.ASPECT_RATIO_11_9;
- }
- return var;
- }
-
- /**
- * Maps the file type used in native layer
- * to file type used in JAVA layer
- *
- * @param fileType The file type in native layer
- *
- * @return The File type in JAVA layer
- */
- int getFileType(int fileType) {
- int retValue = -1;
- switch (fileType) {
- case FileType.UNSUPPORTED:
- retValue = MediaProperties.FILE_UNSUPPORTED;
- break;
- case FileType.THREE_GPP:
- retValue = MediaProperties.FILE_3GP;
- break;
- case FileType.MP4:
- retValue = MediaProperties.FILE_MP4;
- break;
- case FileType.JPG:
- retValue = MediaProperties.FILE_JPEG;
- break;
- case FileType.PNG:
- retValue = MediaProperties.FILE_PNG;
- break;
- case FileType.MP3:
- retValue = MediaProperties.FILE_MP3;
- break;
- case FileType.M4V:
- retValue = MediaProperties.FILE_M4V;
- break;
- case FileType.AMR:
- retValue = MediaProperties.FILE_AMR;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the video codec type used in native layer
- * to video codec type used in JAVA layer
- *
- * @param codecType The video codec type in native layer
- *
- * @return The video codec type in JAVA layer
- */
- int getVideoCodecType(int codecType) {
- int retValue = -1;
- switch (codecType) {
- case VideoFormat.H263:
- retValue = MediaProperties.VCODEC_H263;
- break;
- case VideoFormat.H264:
- retValue = MediaProperties.VCODEC_H264;
- break;
- case VideoFormat.MPEG4:
- retValue = MediaProperties.VCODEC_MPEG4;
- break;
- case VideoFormat.UNSUPPORTED:
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the audio codec type used in native layer
- * to audio codec type used in JAVA layer
- *
- * @param audioType The audio codec type in native layer
- *
- * @return The audio codec type in JAVA layer
- */
- int getAudioCodecType(int codecType) {
- int retValue = -1;
- switch (codecType) {
- case AudioFormat.AMR_NB:
- retValue = MediaProperties.ACODEC_AMRNB;
- break;
- case AudioFormat.AAC:
- retValue = MediaProperties.ACODEC_AAC_LC;
- break;
- case AudioFormat.MP3:
- retValue = MediaProperties.ACODEC_MP3;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Returns the frame rate as integer
- *
- * @param fps The fps as enum
- *
- * @return The frame rate as integer
- */
- int getFrameRate(int fps) {
- int retValue = -1;
- switch (fps) {
- case VideoFrameRate.FR_5_FPS:
- retValue = 5;
- break;
- case VideoFrameRate.FR_7_5_FPS:
- retValue = 8;
- break;
- case VideoFrameRate.FR_10_FPS:
- retValue = 10;
- break;
- case VideoFrameRate.FR_12_5_FPS:
- retValue = 13;
- break;
- case VideoFrameRate.FR_15_FPS:
- retValue = 15;
- break;
- case VideoFrameRate.FR_20_FPS:
- retValue = 20;
- break;
- case VideoFrameRate.FR_25_FPS:
- retValue = 25;
- break;
- case VideoFrameRate.FR_30_FPS:
- retValue = 30;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the file type used in JAVA layer
- * to file type used in native layer
- *
- * @param fileType The file type in JAVA layer
- *
- * @return The File type in native layer
- */
- int getMediaItemFileType(int fileType) {
- int retValue = -1;
-
- switch (fileType) {
- case MediaProperties.FILE_UNSUPPORTED:
- retValue = FileType.UNSUPPORTED;
- break;
- case MediaProperties.FILE_3GP:
- retValue = FileType.THREE_GPP;
- break;
- case MediaProperties.FILE_MP4:
- retValue = FileType.MP4;
- break;
- case MediaProperties.FILE_JPEG:
- retValue = FileType.JPG;
- break;
- case MediaProperties.FILE_PNG:
- retValue = FileType.PNG;
- break;
- case MediaProperties.FILE_M4V:
- retValue = FileType.M4V;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
-
- }
-
- /**
- * Maps the rendering mode used in native layer
- * to rendering mode used in JAVA layer
- *
- * @param renderingMode The rendering mode in JAVA layer
- *
- * @return The rendering mode in native layer
- */
- int getMediaItemRenderingMode(int renderingMode) {
- int retValue = -1;
- switch (renderingMode) {
- case MediaItem.RENDERING_MODE_BLACK_BORDER:
- retValue = MediaRendering.BLACK_BORDERS;
- break;
- case MediaItem.RENDERING_MODE_STRETCH:
- retValue = MediaRendering.RESIZING;
- break;
- case MediaItem.RENDERING_MODE_CROPPING:
- retValue = MediaRendering.CROPPING;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the transition behavior used in JAVA layer
- * to transition behavior used in native layer
- *
- * @param transitionType The transition behavior in JAVA layer
- *
- * @return The transition behavior in native layer
- */
- int getVideoTransitionBehaviour(int transitionType) {
- int retValue = -1;
- switch (transitionType) {
- case Transition.BEHAVIOR_SPEED_UP:
- retValue = TransitionBehaviour.SPEED_UP;
- break;
- case Transition.BEHAVIOR_SPEED_DOWN:
- retValue = TransitionBehaviour.SPEED_DOWN;
- break;
- case Transition.BEHAVIOR_LINEAR:
- retValue = TransitionBehaviour.LINEAR;
- break;
- case Transition.BEHAVIOR_MIDDLE_SLOW:
- retValue = TransitionBehaviour.SLOW_MIDDLE;
- break;
- case Transition.BEHAVIOR_MIDDLE_FAST:
- retValue = TransitionBehaviour.FAST_MIDDLE;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the transition slide direction used in JAVA layer
- * to transition slide direction used in native layer
- *
- * @param slideDirection The transition slide direction
- * in JAVA layer
- *
- * @return The transition slide direction in native layer
- */
- int getSlideSettingsDirection(int slideDirection) {
- int retValue = -1;
- switch (slideDirection) {
- case TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN:
- retValue = SlideDirection.RIGHT_OUT_LEFT_IN;
- break;
- case TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN:
- retValue = SlideDirection.LEFT_OUT_RIGTH_IN;
- break;
- case TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN:
- retValue = SlideDirection.TOP_OUT_BOTTOM_IN;
- break;
- case TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN:
- retValue = SlideDirection.BOTTOM_OUT_TOP_IN;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Maps the effect color type used in JAVA layer
- * to effect color type used in native layer
- *
- * @param effect The EffectColor reference
- *
- * @return The color effect value from native layer
- */
- private int getEffectColorType(EffectColor effect) {
- int retValue = -1;
- switch (effect.getType()) {
- case EffectColor.TYPE_COLOR:
- if (effect.getColor() == EffectColor.GREEN) {
- retValue = VideoEffect.GREEN;
- } else if (effect.getColor() == EffectColor.PINK) {
- retValue = VideoEffect.PINK;
- } else if (effect.getColor() == EffectColor.GRAY) {
- retValue = VideoEffect.BLACK_AND_WHITE;
- } else {
- retValue = VideoEffect.COLORRGB16;
- }
- break;
- case EffectColor.TYPE_GRADIENT:
- retValue = VideoEffect.GRADIENT;
- break;
- case EffectColor.TYPE_SEPIA:
- retValue = VideoEffect.SEPIA;
- break;
- case EffectColor.TYPE_NEGATIVE:
- retValue = VideoEffect.NEGATIVE;
- break;
- case EffectColor.TYPE_FIFTIES:
- retValue = VideoEffect.FIFTIES;
- break;
-
- default:
- retValue = -1;
- }
- return retValue;
- }
-
- /**
- * Calculates video resolution for output clip
- * based on clip's height and aspect ratio of storyboard
- *
- * @param aspectRatio The aspect ratio of story board
- * @param height The height of clip
- *
- * @return The video resolution
- */
- private int findVideoResolution(int aspectRatio, int height) {
- final Pair<Integer, Integer>[] resolutions;
- final Pair<Integer, Integer> maxResolution;
- int retValue = VideoFrameSize.SIZE_UNDEFINED;
- switch (aspectRatio) {
- case MediaProperties.ASPECT_RATIO_3_2:
- if (height == MediaProperties.HEIGHT_480)
- retValue = VideoFrameSize.NTSC;
- else if (height == MediaProperties.HEIGHT_720)
- retValue = VideoFrameSize.W720p;
- break;
- case MediaProperties.ASPECT_RATIO_16_9:
- if (height == MediaProperties.HEIGHT_480)
- retValue = VideoFrameSize.WVGA16x9;
- else if (height == MediaProperties.HEIGHT_720)
- retValue = VideoFrameSize.V720p;
- else if (height == MediaProperties.HEIGHT_1080)
- retValue = VideoFrameSize.V1080p;
- break;
- case MediaProperties.ASPECT_RATIO_4_3:
- if (height == MediaProperties.HEIGHT_480)
- retValue = VideoFrameSize.VGA;
- else if (height == MediaProperties.HEIGHT_720)
- retValue = VideoFrameSize.S720p;
- break;
- case MediaProperties.ASPECT_RATIO_5_3:
- if (height == MediaProperties.HEIGHT_480)
- retValue = VideoFrameSize.WVGA;
- break;
- case MediaProperties.ASPECT_RATIO_11_9:
- if (height == MediaProperties.HEIGHT_144)
- retValue = VideoFrameSize.QCIF;
- else if (height == MediaProperties.HEIGHT_288)
- retValue = VideoFrameSize.CIF;
- break;
- }
- if (retValue == VideoFrameSize.SIZE_UNDEFINED) {
- resolutions = MediaProperties.getSupportedResolutions(mVideoEditor.getAspectRatio());
- // Get the highest resolution
- maxResolution = resolutions[resolutions.length - 1];
- retValue = findVideoResolution(mVideoEditor.getAspectRatio(), maxResolution.second);
- }
-
- return retValue;
- }
-
- /**
- * Calculate a reasonable bitrate for generating intermediate clips.
- */
- private int findVideoBitrate(int videoFrameSize) {
- switch (videoFrameSize) {
- case VideoFrameSize.SQCIF:
- case VideoFrameSize.QQVGA:
- case VideoFrameSize.QCIF:
- return Bitrate.BR_128_KBPS;
- case VideoFrameSize.QVGA:
- case VideoFrameSize.CIF:
- return Bitrate.BR_384_KBPS;
- case VideoFrameSize.VGA:
- case VideoFrameSize.WVGA:
- case VideoFrameSize.NTSC:
- case VideoFrameSize.nHD:
- case VideoFrameSize.WVGA16x9:
- return Bitrate.BR_2_MBPS;
- case VideoFrameSize.V720p:
- case VideoFrameSize.W720p:
- case VideoFrameSize.S720p:
- return Bitrate.BR_5_MBPS;
- case VideoFrameSize.V1080p:
- default:
- return Bitrate.BR_8_MBPS;
- }
- }
-
- /**
- * This method is responsible for exporting a movie
- *
- * @param filePath The output file path
- * @param projectDir The output project directory
- * @param height The height of clip
- * @param bitrate The bitrate at which the movie should be exported
- * @param mediaItemsList The media items list
- * @param mediaTransitionList The transitions list
- * @param mediaBGMList The background track list
- * @param listener The ExportProgressListener
- *
- */
- void export(String filePath, String projectDir, int height, int bitrate,
- List<MediaItem> mediaItemsList, List<Transition> mediaTransitionList,
- List<AudioTrack> mediaBGMList, ExportProgressListener listener) {
-
- int outBitrate = 0;
- mExportFilename = filePath;
- previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
- mExportProgressListener = listener;
- int outVideoProfile = 0;
- int outVideoLevel = 0;
-
- /** Check the platform specific maximum export resolution */
- VideoEditorProfile veProfile = VideoEditorProfile.get();
- if (veProfile == null) {
- throw new RuntimeException("Can't get the video editor profile");
- }
- final int maxOutputHeight = veProfile.maxOutputVideoFrameHeight;
- final int maxOutputWidth = veProfile.maxOutputVideoFrameWidth;
- if (height > maxOutputHeight) {
- throw new IllegalArgumentException(
- "Unsupported export resolution. Supported maximum width:" +
- maxOutputWidth + " height:" + maxOutputHeight +
- " current height:" + height);
- }
- outVideoProfile = VideoEditorProfile.getExportProfile(mExportVideoCodec);
- outVideoLevel = VideoEditorProfile.getExportLevel(mExportVideoCodec);
-
- mProgressToApp = 0;
-
- switch (bitrate) {
- case MediaProperties.BITRATE_28K:
- outBitrate = Bitrate.BR_32_KBPS;
- break;
- case MediaProperties.BITRATE_40K:
- outBitrate = Bitrate.BR_48_KBPS;
- break;
- case MediaProperties.BITRATE_64K:
- outBitrate = Bitrate.BR_64_KBPS;
- break;
- case MediaProperties.BITRATE_96K:
- outBitrate = Bitrate.BR_96_KBPS;
- break;
- case MediaProperties.BITRATE_128K:
- outBitrate = Bitrate.BR_128_KBPS;
- break;
- case MediaProperties.BITRATE_192K:
- outBitrate = Bitrate.BR_192_KBPS;
- break;
- case MediaProperties.BITRATE_256K:
- outBitrate = Bitrate.BR_256_KBPS;
- break;
- case MediaProperties.BITRATE_384K:
- outBitrate = Bitrate.BR_384_KBPS;
- break;
- case MediaProperties.BITRATE_512K:
- outBitrate = Bitrate.BR_512_KBPS;
- break;
- case MediaProperties.BITRATE_800K:
- outBitrate = Bitrate.BR_800_KBPS;
- break;
- case MediaProperties.BITRATE_2M:
- outBitrate = Bitrate.BR_2_MBPS;
- break;
- case MediaProperties.BITRATE_5M:
- outBitrate = Bitrate.BR_5_MBPS;
- break;
- case MediaProperties.BITRATE_8M:
- outBitrate = Bitrate.BR_8_MBPS;
- break;
-
- default:
- throw new IllegalArgumentException("Argument Bitrate incorrect");
- }
- mPreviewEditSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
- mPreviewEditSettings.outputFile = mOutputFilename = filePath;
-
- int aspectRatio = mVideoEditor.getAspectRatio();
- mPreviewEditSettings.videoFrameSize = findVideoResolution(aspectRatio, height);
- mPreviewEditSettings.videoFormat = mExportVideoCodec;
- mPreviewEditSettings.audioFormat = mExportAudioCodec;
- mPreviewEditSettings.videoProfile = outVideoProfile;
- mPreviewEditSettings.videoLevel = outVideoLevel;
- mPreviewEditSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
- mPreviewEditSettings.maxFileSize = 0;
- mPreviewEditSettings.audioChannels = 2;
- mPreviewEditSettings.videoBitrate = outBitrate;
- mPreviewEditSettings.audioBitrate = Bitrate.BR_96_KBPS;
-
- mPreviewEditSettings.transitionSettingsArray = new TransitionSettings[mTotalClips - 1];
- for (int index = 0; index < mTotalClips - 1; index++) {
- mPreviewEditSettings.transitionSettingsArray[index] = new TransitionSettings();
- mPreviewEditSettings.transitionSettingsArray[index].videoTransitionType =
- VideoTransition.NONE;
- mPreviewEditSettings.transitionSettingsArray[index].audioTransitionType =
- AudioTransition.NONE;
- }
-
- for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length; clipCnt++) {
- if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipOriginalPath;
- }
- }
- nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-
- int err = 0;
- try {
- mProcessingState = PROCESSING_EXPORT;
- mProcessingObject = null;
- err = generateClip(mPreviewEditSettings);
- mProcessingState = PROCESSING_NONE;
- } catch (IllegalArgumentException ex) {
- Log.e(TAG, "IllegalArgument for generateClip");
- throw ex;
- } catch (IllegalStateException ex) {
- Log.e(TAG, "IllegalStateExceptiont for generateClip");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "RuntimeException for generateClip");
- throw ex;
- }
-
- if (err != 0) {
- Log.e(TAG, "RuntimeException for generateClip");
- throw new RuntimeException("generateClip failed with error=" + err);
- }
-
- mExportProgressListener = null;
- }
-
- /**
- * This methods takes care of stopping the Export process
- *
- * @param The input file name for which export has to be stopped
- */
- void stop(String filename) {
- try {
- stopEncoding();
- new File(mExportFilename).delete();
- } catch (IllegalStateException ex) {
- Log.e(TAG, "Illegal state exception in unload settings");
- throw ex;
- } catch (RuntimeException ex) {
- Log.e(TAG, "Runtime exception in unload settings");
- throw ex;
- }
- }
-
- /**
- * This method extracts a frame from the input file
- * and returns the frame as a bitmap. See getPixelsList() for more information.
- */
- Bitmap getPixels(String filename, int width, int height, long timeMs,
- int videoRotation) {
- final Bitmap result[] = new Bitmap[1];
- getPixelsList(filename, width, height, timeMs, timeMs, 1, new int[] {0},
- new MediaItem.GetThumbnailListCallback() {
- public void onThumbnail(Bitmap bitmap, int index) {
- result[0] = bitmap;
- }
- }, videoRotation);
- return result[0];
- }
-
- /**
- * This method extracts a list of frame from the
- * input file and returns the frame in bitmap array
- *
- * @param filename The input file name
- * @param width The width of the output frame, before rotation
- * @param height The height of the output frame, before rotation
- * @param startMs The starting time in ms
- * @param endMs The end time in ms
- * @param thumbnailCount The number of frames to be extracted
- * @param indices The indices of thumbnails wanted
- * @param callback The callback used to pass back the bitmaps
- * @param videoRotation The rotation degree need to be done for the bitmap
- *
- * @return The frames as bitmaps in bitmap array
- **/
- void getPixelsList(String filename, final int width, final int height,
- long startMs, long endMs, int thumbnailCount, int[] indices,
- final MediaItem.GetThumbnailListCallback callback,
- final int videoRotation) {
-
- // The decoder needs output width and height as even
- final int decWidth = (width + 1) & 0xFFFFFFFE;
- final int decHeight = (height + 1) & 0xFFFFFFFE;
- final int thumbnailSize = decWidth * decHeight;
-
- // We convert the decoder output (in int[]) to a bitmap by first
- // copy it into an IntBuffer, then use Bitmap.copyPixelsFromBuffer to
- // copy it to the bitmap.
- final int[] decArray = new int[thumbnailSize];
- final IntBuffer decBuffer = IntBuffer.allocate(thumbnailSize);
-
- // If we need to resize and/or rotate the decoder output, we need a
- // temporary bitmap to hold the decoded output.
- final boolean needToMassage =
- (decWidth != width || decHeight != height || videoRotation != 0);
- final Bitmap tmpBitmap = needToMassage
- ? Bitmap.createBitmap(decWidth, decHeight, Bitmap.Config.ARGB_8888)
- : null;
-
- // The final output bitmap width/height may swap because of rotation.
- final boolean needToSwapWH = (videoRotation == 90 || videoRotation == 270);
- final int outWidth = needToSwapWH ? height : width;
- final int outHeight = needToSwapWH ? width : height;
-
- nativeGetPixelsList(filename, decArray, decWidth, decHeight,
- thumbnailCount, startMs, endMs, indices,
- new NativeGetPixelsListCallback() {
- public void onThumbnail(int index) {
- // This is the bitmap we will output to the client
- Bitmap outBitmap = Bitmap.createBitmap(
- outWidth, outHeight, Bitmap.Config.ARGB_8888);
-
- // Copy int[] to IntBuffer
- decBuffer.rewind();
- decBuffer.put(decArray, 0, thumbnailSize);
- decBuffer.rewind();
-
- if (!needToMassage) {
- // We can directly read the decoded result to output bitmap
- outBitmap.copyPixelsFromBuffer(decBuffer);
- } else {
- // Copy the decoded result to an intermediate bitmap first
- tmpBitmap.copyPixelsFromBuffer(decBuffer);
-
- // Create a canvas to resize/rotate the bitmap
- // First scale the decoded bitmap to (0,0)-(1,1), rotate it
- // with (0.5, 0.5) as center, then scale it to
- // (outWidth, outHeight).
- final Canvas canvas = new Canvas(outBitmap);
- Matrix m = new Matrix();
- float sx = 1f / decWidth;
- float sy = 1f / decHeight;
- m.postScale(sx, sy);
- m.postRotate(videoRotation, 0.5f, 0.5f);
- m.postScale(outWidth, outHeight);
- canvas.drawBitmap(tmpBitmap, m, sResizePaint);
- }
- callback.onThumbnail(outBitmap, index);
- }
- });
-
- if (tmpBitmap != null) {
- tmpBitmap.recycle();
- }
- }
-
- interface NativeGetPixelsListCallback {
- public void onThumbnail(int index);
- }
-
- /**
- * This method generates the audio graph
- *
- * @param uniqueId The unique id
- * @param inFileName The inputFile
- * @param OutAudiGraphFileName output filename
- * @param frameDuration The each frame duration
- * @param audioChannels The number of audio channels
- * @param samplesCount Total number of samples count
- * @param listener ExtractAudioWaveformProgressListener reference
- * @param isVideo The flag to indicate if the file is video file or not
- *
- **/
- void generateAudioGraph(String uniqueId, String inFileName, String OutAudiGraphFileName,
- int frameDuration, int audioChannels, int samplesCount,
- ExtractAudioWaveformProgressListener listener, boolean isVideo) {
- String tempPCMFileName;
-
- mExtractAudioWaveformProgressListener = listener;
-
- /**
- * In case of Video, first call will generate the PCM file to make the
- * audio graph
- */
- if (isVideo) {
- tempPCMFileName = String.format(mProjectPath + "/" + uniqueId + ".pcm");
- } else {
- tempPCMFileName = mAudioTrackPCMFilePath;
- }
-
- /**
- * For Video item, generate the PCM
- */
- if (isVideo) {
- nativeGenerateRawAudio(inFileName, tempPCMFileName);
- }
-
- nativeGenerateAudioGraph(tempPCMFileName, OutAudiGraphFileName, frameDuration,
- audioChannels, samplesCount);
-
- /**
- * Once the audio graph file is generated, delete the pcm file
- */
- if (isVideo) {
- new File(tempPCMFileName).delete();
- }
- }
-
- void clearPreviewSurface(Surface surface) {
- nativeClearSurface(surface);
- }
-
- /**
- * Grab the semaphore which arbitrates access to the editor
- *
- * @throws InterruptedException
- */
- private void lock() throws InterruptedException {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbing semaphore", new Throwable());
- }
- mLock.acquire();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbed semaphore");
- }
- }
-
- /**
- * Release the semaphore which arbitrates access to the editor
- */
- private void unlock() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "unlock: releasing semaphore");
- }
- mLock.release();
- }
-
- /** Native Methods */
- native Properties getMediaProperties(String file) throws IllegalArgumentException,
- IllegalStateException, RuntimeException, Exception;
-
- /**
- * Get the version of ManualEdit.
- *
- * @return version of ManualEdit
- * @throws RuntimeException if an error occurred
- * @see Version
- */
- private static native Version getVersion() throws RuntimeException;
-
- /**
- * Returns the video thumbnail in an array of integers. Output format is
- * ARGB8888.
- *
- * @param pixelArray the array that receives the pixel values
- * @param width width of the video thumbnail
- * @param height height of the video thumbnail
- * @param timeMS desired time of the thumbnail in ms
- * @return actual time in ms of the thumbnail generated
- * @throws IllegalStateException if the class has not been initialized
- * @throws IllegalArgumentException if the pixelArray is not available or
- * one of the dimensions is negative or zero or the time is
- * negative
- * @throws RuntimeException on runtime errors in native code
- */
- private native int nativeGetPixels(String fileName, int[] pixelArray, int width, int height,
- long timeMS);
-
- private native int nativeGetPixelsList(String fileName, int[] pixelArray,
- int width, int height, int nosofTN, long startTimeMs,
- long endTimeMs, int[] indices, NativeGetPixelsListCallback callback);
-
- /**
- * Releases the JNI and cleans up the core native module.. Should be called
- * only after init( )
- *
- * @throws IllegalStateException if the method could not be called
- */
- private native void release() throws IllegalStateException, RuntimeException;
-
- /*
- * Clear the preview surface
- */
- private native void nativeClearSurface(Surface surface);
-
- /**
- * Stops the encoding. This method should only be called after encoding has
- * started using method <code> startEncoding</code>
- *
- * @throws IllegalStateException if the method could not be called
- */
- private native void stopEncoding() throws IllegalStateException, RuntimeException;
-
-
- private native void _init(String tempPath, String libraryPath)
- throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
- private native void nativeStartPreview(Surface mSurface, long fromMs, long toMs,
- int callbackAfterFrameCount, boolean loop) throws IllegalArgumentException,
- IllegalStateException, RuntimeException;
-
- private native void nativePopulateSettings(EditSettings editSettings,
- PreviewClipProperties mProperties, AudioSettings mAudioSettings)
- throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
- private native int nativeRenderPreviewFrame(Surface mSurface, long timeMs,
- int surfaceWidth, int surfaceHeight)
- throws IllegalArgumentException,
- IllegalStateException, RuntimeException;
-
- private native int nativeRenderMediaItemPreviewFrame(Surface mSurface, String filepath,
- int framewidth, int frameheight, int surfacewidth, int surfaceheight, long timeMs)
- throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
- private native int nativeStopPreview();
-
- private native int nativeGenerateAudioGraph(String pcmFilePath, String outGraphPath,
- int frameDuration, int channels, int sampleCount);
-
- private native int nativeGenerateRawAudio(String InFileName, String PCMFileName);
-
- private native int nativeGenerateClip(EditSettings editSettings)
- throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
-}
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
deleted file mode 100644
index 590b4ae..0000000
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import java.util.ArrayList;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EditSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.FileType;
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-import android.util.Log;
-import android.util.Pair;
-
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.lang.Math;
-import java.util.List;
-
-/**
- * This class represents an image item on the storyboard. Note that images are
- * scaled down to the maximum supported resolution by preserving the native
- * aspect ratio. To learn the scaled image dimensions use
- * {@link #getScaledWidth()} and {@link #getScaledHeight()} respectively.
- *
- * {@hide}
- */
-public class MediaImageItem extends MediaItem {
- /**
- * Logging
- */
- private static final String TAG = "MediaImageItem";
-
- /**
- * The resize paint
- */
- private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
- /**
- * Instance variables
- */
- private final int mWidth;
- private final int mHeight;
- private final int mAspectRatio;
- private long mDurationMs;
- private int mScaledWidth, mScaledHeight;
- private String mScaledFilename;
- private final VideoEditorImpl mVideoEditor;
- private String mDecodedFilename;
- private int mGeneratedClipHeight;
- private int mGeneratedClipWidth;
- private String mFileName;
-
- private final MediaArtistNativeHelper mMANativeHelper;
-
- /**
- * This class cannot be instantiated by using the default constructor
- */
- @SuppressWarnings("unused")
- private MediaImageItem() throws IOException {
- this(null, null, null, 0, RENDERING_MODE_BLACK_BORDER);
- }
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param mediaItemId The media item id
- * @param filename The image file name
- * @param durationMs The duration of the image on the storyboard
- * @param renderingMode The rendering mode
- *
- * @throws IOException
- */
- public MediaImageItem(VideoEditor editor, String mediaItemId, String filename, long durationMs,
- int renderingMode) throws IOException {
-
- super(editor, mediaItemId, filename, renderingMode);
-
- mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
- mVideoEditor = ((VideoEditorImpl)editor);
- try {
- final Properties properties = mMANativeHelper.getMediaProperties(filename);
-
- switch (mMANativeHelper.getFileType(properties.fileType)) {
- case MediaProperties.FILE_JPEG:
- case MediaProperties.FILE_PNG: {
- break;
- }
-
- default: {
- throw new IllegalArgumentException("Unsupported Input File Type");
- }
- }
- } catch (Exception e) {
- throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
- }
- mFileName = filename;
- /**
- * Determine the dimensions of the image
- */
- final BitmapFactory.Options dbo = new BitmapFactory.Options();
- dbo.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(filename, dbo);
-
- mWidth = dbo.outWidth;
- mHeight = dbo.outHeight;
- mDurationMs = durationMs;
- mDecodedFilename = String.format(mMANativeHelper.getProjectPath() +
- "/" + "decoded" + getId()+ ".rgb");
-
- try {
- mAspectRatio = mMANativeHelper.getAspectRatio(mWidth, mHeight);
- } catch(IllegalArgumentException e) {
- throw new IllegalArgumentException ("Null width and height");
- }
-
- mGeneratedClipHeight = 0;
- mGeneratedClipWidth = 0;
-
- /**
- * Images are stored in memory scaled to the maximum resolution to
- * save memory.
- */
- final Pair<Integer, Integer>[] resolutions =
- MediaProperties.getSupportedResolutions(mAspectRatio);
-
- /**
- * Get the highest resolution
- */
- final Pair<Integer, Integer> maxResolution = resolutions[resolutions.length - 1];
-
- final Bitmap imageBitmap;
-
- if (mWidth > maxResolution.first || mHeight > maxResolution.second) {
- /**
- * We need to scale the image
- */
- imageBitmap = scaleImage(filename, maxResolution.first,
- maxResolution.second);
- mScaledFilename = String.format(mMANativeHelper.getProjectPath() +
- "/" + "scaled" + getId()+ ".JPG");
- if (!((new File(mScaledFilename)).exists())) {
- super.mRegenerateClip = true;
- final FileOutputStream f1 = new FileOutputStream(mScaledFilename);
- imageBitmap.compress(Bitmap.CompressFormat.JPEG, 50,f1);
- f1.close();
- }
- mScaledWidth = (imageBitmap.getWidth() >> 1) << 1;
- mScaledHeight = (imageBitmap.getHeight() >> 1) << 1;
- } else {
- mScaledFilename = filename;
- mScaledWidth = (mWidth >> 1) << 1;
- mScaledHeight = (mHeight >> 1) << 1;
- imageBitmap = BitmapFactory.decodeFile(mScaledFilename);
- }
- int newWidth = mScaledWidth;
- int newHeight = mScaledHeight;
- if (!((new File(mDecodedFilename)).exists())) {
- final FileOutputStream fl = new FileOutputStream(mDecodedFilename);
- final DataOutputStream dos = new DataOutputStream(fl);
- final int [] framingBuffer = new int[newWidth];
- final ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
- IntBuffer intBuffer;
- final byte[] array = byteBuffer.array();
- int tmp = 0;
- while (tmp < newHeight) {
- imageBitmap.getPixels(framingBuffer, 0, mScaledWidth, 0,
- tmp, newWidth, 1);
- intBuffer = byteBuffer.asIntBuffer();
- intBuffer.put(framingBuffer, 0, newWidth);
- dos.write(array);
- tmp += 1;
- }
- fl.close();
- }
- imageBitmap.recycle();
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getFileType() {
- if (mFilename.endsWith(".jpg") || mFilename.endsWith(".jpeg")
- || mFilename.endsWith(".JPG") || mFilename.endsWith(".JPEG")) {
- return MediaProperties.FILE_JPEG;
- } else if (mFilename.endsWith(".png") || mFilename.endsWith(".PNG")) {
- return MediaProperties.FILE_PNG;
- } else {
- return MediaProperties.FILE_UNSUPPORTED;
- }
- }
-
- /**
- * @return The scaled image file name
- */
- String getScaledImageFileName() {
- return mScaledFilename;
- }
-
- /**
- * @return The generated Kenburns clip height.
- */
- int getGeneratedClipHeight() {
- return mGeneratedClipHeight;
- }
-
- /**
- * @return The generated Kenburns clip width.
- */
- int getGeneratedClipWidth() {
- return mGeneratedClipWidth;
- }
-
- /**
- * @return The file name of image which is decoded and stored
- * in RGB format
- */
- String getDecodedImageFileName() {
- return mDecodedFilename;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getWidth() {
- return mWidth;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getHeight() {
- return mHeight;
- }
-
- /**
- * @return The scaled width of the image.
- */
- public int getScaledWidth() {
- return mScaledWidth;
- }
-
- /**
- * @return The scaled height of the image.
- */
- public int getScaledHeight() {
- return mScaledHeight;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getAspectRatio() {
- return mAspectRatio;
- }
-
- /**
- * This method will adjust the duration of bounding transitions, effects
- * and overlays if the current duration of the transactions become greater
- * than the maximum allowable duration.
- *
- * @param durationMs The duration of the image in the storyboard timeline
- */
- public void setDuration(long durationMs) {
- if (durationMs == mDurationMs) {
- return;
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- /**
- * Invalidate the end transitions if necessary.
- * This invalidation is necessary for the case in which an effect or
- * an overlay is overlapping with the end transition
- * (before the duration is changed) and it no longer overlaps with the
- * transition after the duration is increased.
- *
- * The beginning transition does not need to be invalidated at this time
- * because an effect or an overlay overlaps with the beginning
- * transition, the begin transition is unaffected by a media item
- * duration change.
- */
- invalidateEndTransition();
-
- mDurationMs = durationMs;
-
- adjustTransitions();
- final List<Overlay> adjustedOverlays = adjustOverlays();
- final List<Effect> adjustedEffects = adjustEffects();
-
- /**
- * Invalidate the beginning and end transitions after adjustments.
- * This invalidation is necessary for the case in which an effect or
- * an overlay was not overlapping with the beginning or end transitions
- * before the setDuration reduces the duration of the media item and
- * causes an overlap of the beginning and/or end transition with the
- * effect.
- */
- invalidateBeginTransition(adjustedEffects, adjustedOverlays);
- invalidateEndTransition();
- if (getGeneratedImageClip() != null) {
- /*
- * Delete the file
- */
- new File(getGeneratedImageClip()).delete();
- /*
- * Invalidate the filename
- */
- setGeneratedImageClip(null);
- super.setRegenerateClip(true);
- }
- mVideoEditor.updateTimelineDuration();
- }
-
- /**
- * Invalidate the begin transition if any effects and overlays overlap
- * with the begin transition.
- *
- * @param effects List of effects to check for transition overlap
- * @param overlays List of overlays to check for transition overlap
- */
- private void invalidateBeginTransition(List<Effect> effects, List<Overlay> overlays) {
- if (mBeginTransition != null && mBeginTransition.isGenerated()) {
- final long transitionDurationMs = mBeginTransition.getDuration();
-
- /**
- * The begin transition must be invalidated if it overlaps with
- * an effect.
- */
- for (Effect effect : effects) {
- /**
- * Check if the effect overlaps with the begin transition
- */
- if (effect.getStartTime() < transitionDurationMs) {
- mBeginTransition.invalidate();
- break;
- }
- }
-
- if (mBeginTransition.isGenerated()) {
- /**
- * The end transition must be invalidated if it overlaps with
- * an overlay.
- */
- for (Overlay overlay : overlays) {
- /**
- * Check if the overlay overlaps with the end transition
- */
- if (overlay.getStartTime() < transitionDurationMs) {
- mBeginTransition.invalidate();
- break;
- }
- }
- }
- }
- }
-
- /**
- * Invalidate the end transition if any effects and overlays overlap
- * with the end transition.
- */
- private void invalidateEndTransition() {
- if (mEndTransition != null && mEndTransition.isGenerated()) {
- final long transitionDurationMs = mEndTransition.getDuration();
-
- /**
- * The end transition must be invalidated if it overlaps with
- * an effect.
- */
- final List<Effect> effects = getAllEffects();
- for (Effect effect : effects) {
- /**
- * Check if the effect overlaps with the end transition
- */
- if (effect.getStartTime() + effect.getDuration() >
- mDurationMs - transitionDurationMs) {
- mEndTransition.invalidate();
- break;
- }
- }
-
- if (mEndTransition.isGenerated()) {
- /**
- * The end transition must be invalidated if it overlaps with
- * an overlay.
- */
- final List<Overlay> overlays = getAllOverlays();
- for (Overlay overlay : overlays) {
- /**
- * Check if the overlay overlaps with the end transition
- */
- if (overlay.getStartTime() + overlay.getDuration() >
- mDurationMs - transitionDurationMs) {
- mEndTransition.invalidate();
- break;
- }
- }
- }
- }
- }
-
- /**
- * Adjust the start time and/or duration of effects.
- *
- * @return The list of effects which were adjusted
- */
- private List<Effect> adjustEffects() {
- final List<Effect> adjustedEffects = new ArrayList<Effect>();
- final List<Effect> effects = getAllEffects();
- for (Effect effect : effects) {
- /**
- * Adjust the start time if necessary
- */
- final long effectStartTimeMs;
- if (effect.getStartTime() > getDuration()) {
- effectStartTimeMs = 0;
- } else {
- effectStartTimeMs = effect.getStartTime();
- }
-
- /**
- * Adjust the duration if necessary
- */
- final long effectDurationMs;
- if (effectStartTimeMs + effect.getDuration() > getDuration()) {
- effectDurationMs = getDuration() - effectStartTimeMs;
- } else {
- effectDurationMs = effect.getDuration();
- }
-
- if (effectStartTimeMs != effect.getStartTime() ||
- effectDurationMs != effect.getDuration()) {
- effect.setStartTimeAndDuration(effectStartTimeMs, effectDurationMs);
- adjustedEffects.add(effect);
- }
- }
-
- return adjustedEffects;
- }
-
- /**
- * Adjust the start time and/or duration of overlays.
- *
- * @return The list of overlays which were adjusted
- */
- private List<Overlay> adjustOverlays() {
- final List<Overlay> adjustedOverlays = new ArrayList<Overlay>();
- final List<Overlay> overlays = getAllOverlays();
- for (Overlay overlay : overlays) {
- /**
- * Adjust the start time if necessary
- */
- final long overlayStartTimeMs;
- if (overlay.getStartTime() > getDuration()) {
- overlayStartTimeMs = 0;
- } else {
- overlayStartTimeMs = overlay.getStartTime();
- }
-
- /**
- * Adjust the duration if necessary
- */
- final long overlayDurationMs;
- if (overlayStartTimeMs + overlay.getDuration() > getDuration()) {
- overlayDurationMs = getDuration() - overlayStartTimeMs;
- } else {
- overlayDurationMs = overlay.getDuration();
- }
-
- if (overlayStartTimeMs != overlay.getStartTime() ||
- overlayDurationMs != overlay.getDuration()) {
- overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);
- adjustedOverlays.add(overlay);
- }
- }
-
- return adjustedOverlays;
- }
- /**
- * This function get the proper width by given aspect ratio
- * and height.
- *
- * @param aspectRatio Given aspect ratio
- * @param height Given height
- */
- private int getWidthByAspectRatioAndHeight(int aspectRatio, int height) {
- int width = 0;
-
- switch (aspectRatio) {
- case MediaProperties.ASPECT_RATIO_3_2:
- if (height == MediaProperties.HEIGHT_480)
- width = 720;
- else if (height == MediaProperties.HEIGHT_720)
- width = 1080;
- break;
-
- case MediaProperties.ASPECT_RATIO_16_9:
- if (height == MediaProperties.HEIGHT_360)
- width = 640;
- else if (height == MediaProperties.HEIGHT_480)
- width = 854;
- else if (height == MediaProperties.HEIGHT_720)
- width = 1280;
- else if (height == MediaProperties.HEIGHT_1080)
- width = 1920;
- break;
-
- case MediaProperties.ASPECT_RATIO_4_3:
- if (height == MediaProperties.HEIGHT_480)
- width = 640;
- if (height == MediaProperties.HEIGHT_720)
- width = 960;
- break;
-
- case MediaProperties.ASPECT_RATIO_5_3:
- if (height == MediaProperties.HEIGHT_480)
- width = 800;
- break;
-
- case MediaProperties.ASPECT_RATIO_11_9:
- if (height == MediaProperties.HEIGHT_144)
- width = 176;
- break;
-
- default : {
- throw new IllegalArgumentException(
- "Illegal arguments for aspectRatio");
- }
- }
-
- return width;
- }
-
- /**
- * This function sets the Ken Burn effect generated clip
- * name.
- *
- * @param generatedFilePath The name of the generated clip
- */
- @Override
- void setGeneratedImageClip(String generatedFilePath) {
- super.setGeneratedImageClip(generatedFilePath);
-
- // set the Kenburns clip width and height
- mGeneratedClipHeight = getScaledHeight();
- mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
- mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
- }
-
- /**
- * @return The name of the image clip
- * generated with ken burns effect.
- */
- @Override
- String getGeneratedImageClip() {
- return super.getGeneratedImageClip();
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public long getDuration() {
- return mDurationMs;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public long getTimelineDuration() {
- return mDurationMs;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public Bitmap getThumbnail(int width, int height, long timeMs) throws IOException {
- if (getGeneratedImageClip() != null) {
- return mMANativeHelper.getPixels(getGeneratedImageClip(),
- width, height, timeMs, 0);
- } else {
- return scaleImage(mFilename, width, height);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public void getThumbnailList(int width, int height,
- long startMs, long endMs,
- int thumbnailCount,
- int[] indices,
- GetThumbnailListCallback callback)
- throws IOException {
- //KenBurns was not applied on this.
- if (getGeneratedImageClip() == null) {
- final Bitmap thumbnail = scaleImage(mFilename, width, height);
- for (int i = 0; i < indices.length; i++) {
- callback.onThumbnail(thumbnail, indices[i]);
- }
- } else {
- if (startMs > endMs) {
- throw new IllegalArgumentException("Start time is greater than end time");
- }
-
- if (endMs > mDurationMs) {
- throw new IllegalArgumentException("End time is greater than file duration");
- }
-
- mMANativeHelper.getPixelsList(getGeneratedImageClip(), width,
- height, startMs, endMs, thumbnailCount, indices, callback, 0);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void invalidateTransitions(long startTimeMs, long durationMs) {
- /**
- * Check if the item overlaps with the beginning and end transitions
- */
- if (mBeginTransition != null) {
- if (isOverlapping(startTimeMs, durationMs, 0, mBeginTransition.getDuration())) {
- mBeginTransition.invalidate();
- }
- }
-
- if (mEndTransition != null) {
- final long transitionDurationMs = mEndTransition.getDuration();
- if (isOverlapping(startTimeMs, durationMs,
- getDuration() - transitionDurationMs, transitionDurationMs)) {
- mEndTransition.invalidate();
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs,
- long newDurationMs) {
- /**
- * Check if the item overlaps with the beginning and end transitions
- */
- if (mBeginTransition != null) {
- final long transitionDurationMs = mBeginTransition.getDuration();
- final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, 0,
- transitionDurationMs);
- final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, 0,
- transitionDurationMs);
- /**
- * Invalidate transition if:
- *
- * 1. New item overlaps the transition, the old one did not
- * 2. New item does not overlap the transition, the old one did
- * 3. New and old item overlap the transition if begin or end
- * time changed
- */
- if (newOverlap != oldOverlap) { // Overlap has changed
- mBeginTransition.invalidate();
- } else if (newOverlap) { // Both old and new overlap
- if ((oldStartTimeMs != newStartTimeMs) ||
- !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
- newStartTimeMs + newDurationMs > transitionDurationMs)) {
- mBeginTransition.invalidate();
- }
- }
- }
-
- if (mEndTransition != null) {
- final long transitionDurationMs = mEndTransition.getDuration();
- final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
- mDurationMs - transitionDurationMs, transitionDurationMs);
- final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
- mDurationMs - transitionDurationMs, transitionDurationMs);
- /**
- * Invalidate transition if:
- *
- * 1. New item overlaps the transition, the old one did not
- * 2. New item does not overlap the transition, the old one did
- * 3. New and old item overlap the transition if begin or end
- * time changed
- */
- if (newOverlap != oldOverlap) { // Overlap has changed
- mEndTransition.invalidate();
- } else if (newOverlap) { // Both old and new overlap
- if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
- ((oldStartTimeMs > mDurationMs - transitionDurationMs) ||
- newStartTimeMs > mDurationMs - transitionDurationMs)) {
- mEndTransition.invalidate();
- }
- }
- }
- }
-
- /**
- * This function invalidates the rgb image clip,ken burns effect clip,
- * and scaled image clip
- */
- void invalidate() {
- if (getGeneratedImageClip() != null) {
- new File(getGeneratedImageClip()).delete();
- setGeneratedImageClip(null);
- setRegenerateClip(true);
- }
-
- if (mScaledFilename != null) {
- if(mFileName != mScaledFilename) {
- new File(mScaledFilename).delete();
- }
- mScaledFilename = null;
- }
-
- if (mDecodedFilename != null) {
- new File(mDecodedFilename).delete();
- mDecodedFilename = null;
- }
- }
-
- /**
- * @param KenBurnEffect object.
- * @return an Object of {@link ClipSettings} with Ken Burn settings
- * needed to generate the clip
- */
- private ClipSettings getKenBurns(EffectKenBurns effectKB) {
- int PanZoomXa;
- int PanZoomXb;
- int width = 0, height = 0;
- Rect start = new Rect();
- Rect end = new Rect();
- ClipSettings clipSettings = null;
- clipSettings = new ClipSettings();
- /**
- * image:
- ---------------------------------------
- | Xa |
- | Ya --------------- |
- | | | |
- | | | |
- | --------------- Xb ratioB |
- | ratioA ------- |
- | Yb | | |
- | | | |
- | ------- |
- ---------------------------------------
- */
-
- effectKB.getKenBurnsSettings(start, end);
- width = getWidth();
- height = getHeight();
- if ((start.left < 0) || (start.left > width) || (start.right < 0) || (start.right > width)
- || (start.top < 0) || (start.top > height) || (start.bottom < 0)
- || (start.bottom > height) || (end.left < 0) || (end.left > width)
- || (end.right < 0) || (end.right > width) || (end.top < 0) || (end.top > height)
- || (end.bottom < 0) || (end.bottom > height)) {
- throw new IllegalArgumentException("Illegal arguments for KebBurns");
- }
-
- if (((width - (start.right - start.left) == 0) || (height - (start.bottom - start.top) == 0))
- && ((width - (end.right - end.left) == 0) || (height - (end.bottom - end.top) == 0))) {
- setRegenerateClip(false);
- clipSettings.clipPath = getDecodedImageFileName();
- clipSettings.fileType = FileType.JPG;
- clipSettings.beginCutTime = 0;
- clipSettings.endCutTime = (int)getTimelineDuration();
- clipSettings.beginCutPercent = 0;
- clipSettings.endCutPercent = 0;
- clipSettings.panZoomEnabled = false;
- clipSettings.panZoomPercentStart = 0;
- clipSettings.panZoomTopLeftXStart = 0;
- clipSettings.panZoomTopLeftYStart = 0;
- clipSettings.panZoomPercentEnd = 0;
- clipSettings.panZoomTopLeftXEnd = 0;
- clipSettings.panZoomTopLeftYEnd = 0;
- clipSettings.mediaRendering = mMANativeHelper
- .getMediaItemRenderingMode(getRenderingMode());
-
- clipSettings.rgbWidth = getScaledWidth();
- clipSettings.rgbHeight = getScaledHeight();
-
- return clipSettings;
- }
-
- PanZoomXa = (1000 * start.width()) / width;
- PanZoomXb = (1000 * end.width()) / width;
-
- clipSettings.clipPath = getDecodedImageFileName();
- clipSettings.fileType = mMANativeHelper.getMediaItemFileType(getFileType());
- clipSettings.beginCutTime = 0;
- clipSettings.endCutTime = (int)getTimelineDuration();
- clipSettings.beginCutPercent = 0;
- clipSettings.endCutPercent = 0;
- clipSettings.panZoomEnabled = true;
- clipSettings.panZoomPercentStart = PanZoomXa;
- clipSettings.panZoomTopLeftXStart = (start.left * 1000) / width;
- clipSettings.panZoomTopLeftYStart = (start.top * 1000) / height;
- clipSettings.panZoomPercentEnd = PanZoomXb;
- clipSettings.panZoomTopLeftXEnd = (end.left * 1000) / width;
- clipSettings.panZoomTopLeftYEnd = (end.top * 1000) / height;
- clipSettings.mediaRendering
- = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
-
- clipSettings.rgbWidth = getScaledWidth();
- clipSettings.rgbHeight = getScaledHeight();
-
- return clipSettings;
- }
-
-
- /**
- * @param KenBurnEffect object.
- * @return an Object of {@link ClipSettings} with Ken Burns
- * generated clip name
- */
- ClipSettings generateKenburnsClip(EffectKenBurns effectKB) {
- EditSettings editSettings = new EditSettings();
- editSettings.clipSettingsArray = new ClipSettings[1];
- String output = null;
- ClipSettings clipSettings = new ClipSettings();
- initClipSettings(clipSettings);
- editSettings.clipSettingsArray[0] = getKenBurns(effectKB);
- if ((getGeneratedImageClip() == null) && (getRegenerateClip())) {
- output = mMANativeHelper.generateKenBurnsClip(editSettings, this);
- setGeneratedImageClip(output);
- setRegenerateClip(false);
- clipSettings.clipPath = output;
- clipSettings.fileType = FileType.THREE_GPP;
-
- mGeneratedClipHeight = getScaledHeight();
- mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
- mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
- } else {
- if (getGeneratedImageClip() == null) {
- clipSettings.clipPath = getDecodedImageFileName();
- clipSettings.fileType = FileType.JPG;
-
- clipSettings.rgbWidth = getScaledWidth();
- clipSettings.rgbHeight = getScaledHeight();
-
- } else {
- clipSettings.clipPath = getGeneratedImageClip();
- clipSettings.fileType = FileType.THREE_GPP;
- }
- }
- clipSettings.mediaRendering = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
- clipSettings.beginCutTime = 0;
- clipSettings.endCutTime = (int)getTimelineDuration();
-
- return clipSettings;
- }
-
- /**
- * @return an Object of {@link ClipSettings} with Image Clip
- * properties data populated.If the image has Ken Burns effect applied,
- * then file path contains generated image clip name with Ken Burns effect
- */
- ClipSettings getImageClipProperties() {
- ClipSettings clipSettings = new ClipSettings();
- List<Effect> effects = null;
- EffectKenBurns effectKB = null;
- boolean effectKBPresent = false;
-
- effects = getAllEffects();
- for (Effect effect : effects) {
- if (effect instanceof EffectKenBurns) {
- effectKB = (EffectKenBurns)effect;
- effectKBPresent = true;
- break;
- }
- }
-
- if (effectKBPresent) {
- clipSettings = generateKenburnsClip(effectKB);
- } else {
- /**
- * Init the clip settings object
- */
- initClipSettings(clipSettings);
- clipSettings.clipPath = getDecodedImageFileName();
- clipSettings.fileType = FileType.JPG;
- clipSettings.beginCutTime = 0;
- clipSettings.endCutTime = (int)getTimelineDuration();
- clipSettings.mediaRendering = mMANativeHelper
- .getMediaItemRenderingMode(getRenderingMode());
- clipSettings.rgbWidth = getScaledWidth();
- clipSettings.rgbHeight = getScaledHeight();
-
- }
- return clipSettings;
- }
-
- /**
- * Resize a bitmap to the specified width and height
- *
- * @param filename The filename
- * @param width The thumbnail width
- * @param height The thumbnail height
- *
- * @return The resized bitmap
- */
- private Bitmap scaleImage(String filename, int width, int height)
- throws IOException {
- final BitmapFactory.Options dbo = new BitmapFactory.Options();
- dbo.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(filename, dbo);
-
- final int nativeWidth = dbo.outWidth;
- final int nativeHeight = dbo.outHeight;
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "generateThumbnail: Input: " + nativeWidth + "x" + nativeHeight
- + ", resize to: " + width + "x" + height);
- }
-
- final Bitmap srcBitmap;
- float bitmapWidth, bitmapHeight;
- if (nativeWidth > width || nativeHeight > height) {
- float dx = ((float)nativeWidth) / ((float)width);
- float dy = ((float)nativeHeight) / ((float)height);
-
- if (dx > dy) {
- bitmapWidth = width;
-
- if (((float)nativeHeight / dx) < (float)height) {
- bitmapHeight = (float)Math.ceil(nativeHeight / dx);
- } else { // value equals the requested height
- bitmapHeight = (float)Math.floor(nativeHeight / dx);
- }
-
- } else {
- if (((float)nativeWidth / dy) > (float)width) {
- bitmapWidth = (float)Math.floor(nativeWidth / dy);
- } else { // value equals the requested width
- bitmapWidth = (float)Math.ceil(nativeWidth / dy);
- }
-
- bitmapHeight = height;
- }
-
- /**
- * Create the bitmap from file
- */
- int sampleSize = (int) Math.ceil(Math.max(
- (float) nativeWidth / bitmapWidth,
- (float) nativeHeight / bitmapHeight));
- sampleSize = nextPowerOf2(sampleSize);
- final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inSampleSize = sampleSize;
- srcBitmap = BitmapFactory.decodeFile(filename, options);
- } else {
- bitmapWidth = width;
- bitmapHeight = height;
- srcBitmap = BitmapFactory.decodeFile(filename);
-
- }
-
- if (srcBitmap == null) {
- Log.e(TAG, "generateThumbnail: Cannot decode image bytes");
- throw new IOException("Cannot decode file: " + mFilename);
- }
-
- /**
- * Create the canvas bitmap
- */
- final Bitmap bitmap = Bitmap.createBitmap((int)bitmapWidth,
- (int)bitmapHeight,
- Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(bitmap);
- canvas.drawBitmap(srcBitmap, new Rect(0, 0, srcBitmap.getWidth(),
- srcBitmap.getHeight()),
- new Rect(0, 0, (int)bitmapWidth,
- (int)bitmapHeight), sResizePaint);
- canvas.setBitmap(null);
- /**
- * Release the source bitmap
- */
- srcBitmap.recycle();
- return bitmap;
- }
-
- public static int nextPowerOf2(int n) {
- n -= 1;
- n |= n >>> 16;
- n |= n >>> 8;
- n |= n >>> 4;
- n |= n >>> 2;
- n |= n >>> 1;
- return n + 1;
- }
-}
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
deleted file mode 100644
index 4e9ea75..0000000
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import java.io.DataOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.FileType;
-import android.media.videoeditor.MediaArtistNativeHelper.MediaRendering;
-
-/**
- * This abstract class describes the base class for any MediaItem. Objects are
- * defined with a file path as a source data.
- * {@hide}
- */
-public abstract class MediaItem {
- /**
- * A constant which can be used to specify the end of the file (instead of
- * providing the actual duration of the media item).
- */
- public final static int END_OF_FILE = -1;
-
- /**
- * Rendering modes
- */
- /**
- * When using the RENDERING_MODE_BLACK_BORDER rendering mode video frames
- * are resized by preserving the aspect ratio until the movie matches one of
- * the dimensions of the output movie. The areas outside the resized video
- * clip are rendered black.
- */
- public static final int RENDERING_MODE_BLACK_BORDER = 0;
-
- /**
- * When using the RENDERING_MODE_STRETCH rendering mode video frames are
- * stretched horizontally or vertically to match the current aspect ratio of
- * the video editor.
- */
- public static final int RENDERING_MODE_STRETCH = 1;
-
- /**
- * When using the RENDERING_MODE_CROPPING rendering mode video frames are
- * scaled horizontally or vertically by preserving the original aspect ratio
- * of the media item.
- */
- public static final int RENDERING_MODE_CROPPING = 2;
-
- /**
- * The unique id of the MediaItem
- */
- private final String mUniqueId;
-
- /**
- * The name of the file associated with the MediaItem
- */
- protected final String mFilename;
-
- /**
- * List of effects
- */
- private final List<Effect> mEffects;
-
- /**
- * List of overlays
- */
- private final List<Overlay> mOverlays;
-
- /**
- * The rendering mode
- */
- private int mRenderingMode;
-
- private final MediaArtistNativeHelper mMANativeHelper;
-
- private final String mProjectPath;
-
- /**
- * Beginning and end transitions
- */
- protected Transition mBeginTransition;
-
- protected Transition mEndTransition;
-
- protected String mGeneratedImageClip;
-
- protected boolean mRegenerateClip;
-
- private boolean mBlankFrameGenerated = false;
-
- private String mBlankFrameFilename = null;
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param mediaItemId The MediaItem id
- * @param filename name of the media file.
- * @param renderingMode The rendering mode
- * @throws IOException if file is not found
- * @throws IllegalArgumentException if a capability such as file format is
- * not supported the exception object contains the unsupported
- * capability
- */
- protected MediaItem(VideoEditor editor, String mediaItemId, String filename,
- int renderingMode) throws IOException {
- if (filename == null) {
- throw new IllegalArgumentException("MediaItem : filename is null");
- }
- File file = new File(filename);
- if (!file.exists()) {
- throw new IOException(filename + " not found ! ");
- }
-
- /*Compare file_size with 2GB*/
- if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) {
- throw new IllegalArgumentException("File size is more than 2GB");
- }
- mUniqueId = mediaItemId;
- mFilename = filename;
- mRenderingMode = renderingMode;
- mEffects = new ArrayList<Effect>();
- mOverlays = new ArrayList<Overlay>();
- mBeginTransition = null;
- mEndTransition = null;
- mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
- mProjectPath = editor.getPath();
- mRegenerateClip = false;
- mGeneratedImageClip = null;
- }
-
- /**
- * @return The id of the media item
- */
- public String getId() {
- return mUniqueId;
- }
-
- /**
- * @return The media source file name
- */
- public String getFilename() {
- return mFilename;
- }
-
- /**
- * If aspect ratio of the MediaItem is different from the aspect ratio of
- * the editor then this API controls the rendering mode.
- *
- * @param renderingMode rendering mode. It is one of:
- * {@link #RENDERING_MODE_BLACK_BORDER},
- * {@link #RENDERING_MODE_STRETCH}
- */
- public void setRenderingMode(int renderingMode) {
- switch (renderingMode) {
- case RENDERING_MODE_BLACK_BORDER:
- case RENDERING_MODE_STRETCH:
- case RENDERING_MODE_CROPPING:
- break;
-
- default:
- throw new IllegalArgumentException("Invalid Rendering Mode");
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- mRenderingMode = renderingMode;
- if (mBeginTransition != null) {
- mBeginTransition.invalidate();
- }
-
- if (mEndTransition != null) {
- mEndTransition.invalidate();
- }
-
- for (Overlay overlay : mOverlays) {
- ((OverlayFrame)overlay).invalidateGeneratedFiles();
- }
- }
-
- /**
- * @return The rendering mode
- */
- public int getRenderingMode() {
- return mRenderingMode;
- }
-
- /**
- * @param transition The beginning transition
- */
- void setBeginTransition(Transition transition) {
- mBeginTransition = transition;
- }
-
- /**
- * @return The begin transition
- */
- public Transition getBeginTransition() {
- return mBeginTransition;
- }
-
- /**
- * @param transition The end transition
- */
- void setEndTransition(Transition transition) {
- mEndTransition = transition;
- }
-
- /**
- * @return The end transition
- */
- public Transition getEndTransition() {
- return mEndTransition;
- }
-
- /**
- * @return The timeline duration. This is the actual duration in the
- * timeline (trimmed duration)
- */
- public abstract long getTimelineDuration();
-
- /**
- * @return The is the full duration of the media item (not trimmed)
- */
- public abstract long getDuration();
-
- /**
- * @return The source file type
- */
- public abstract int getFileType();
-
- /**
- * @return Get the native width of the media item
- */
- public abstract int getWidth();
-
- /**
- * @return Get the native height of the media item
- */
- public abstract int getHeight();
-
- /**
- * Get aspect ratio of the source media item.
- *
- * @return the aspect ratio as described in MediaProperties.
- * MediaProperties.ASPECT_RATIO_UNDEFINED if aspect ratio is not
- * supported as in MediaProperties
- */
- public abstract int getAspectRatio();
-
- /**
- * Add the specified effect to this media item.
- *
- * Note that certain types of effects cannot be applied to video and to
- * image media items. For example in certain implementation a Ken Burns
- * implementation cannot be applied to video media item.
- *
- * This method invalidates transition video clips if the
- * effect overlaps with the beginning and/or the end transition.
- *
- * @param effect The effect to apply
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if the effect start and/or duration are
- * invalid or if the effect cannot be applied to this type of media
- * item or if the effect id is not unique across all the Effects
- * added.
- */
- public void addEffect(Effect effect) {
-
- if (effect == null) {
- throw new IllegalArgumentException("NULL effect cannot be applied");
- }
-
- if (effect.getMediaItem() != this) {
- throw new IllegalArgumentException("Media item mismatch");
- }
-
- if (mEffects.contains(effect)) {
- throw new IllegalArgumentException("Effect already exists: " + effect.getId());
- }
-
- if (effect.getStartTime() + effect.getDuration() > getDuration()) {
- throw new IllegalArgumentException(
- "Effect start time + effect duration > media clip duration");
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- mEffects.add(effect);
-
- invalidateTransitions(effect.getStartTime(), effect.getDuration());
-
- if (effect instanceof EffectKenBurns) {
- mRegenerateClip = true;
- }
- }
-
- /**
- * Remove the effect with the specified id.
- *
- * This method invalidates a transition video clip if the effect overlaps
- * with a transition.
- *
- * @param effectId The id of the effect to be removed
- *
- * @return The effect that was removed
- * @throws IllegalStateException if a preview or an export is in progress
- */
- public Effect removeEffect(String effectId) {
- for (Effect effect : mEffects) {
- if (effect.getId().equals(effectId)) {
- mMANativeHelper.setGeneratePreview(true);
-
- mEffects.remove(effect);
-
- invalidateTransitions(effect.getStartTime(), effect.getDuration());
- if (effect instanceof EffectKenBurns) {
- if (mGeneratedImageClip != null) {
- /**
- * Delete the file
- */
- new File(mGeneratedImageClip).delete();
- /**
- * Invalidate the filename
- */
- mGeneratedImageClip = null;
- }
- mRegenerateClip = false;
- }
- return effect;
- }
- }
- return null;
- }
-
- /**
- * Set the filepath of the generated image clip when the effect is added.
- *
- * @param The filepath of the generated image clip.
- */
- void setGeneratedImageClip(String generatedFilePath) {
- mGeneratedImageClip = generatedFilePath;
- }
-
- /**
- * Get the filepath of the generated image clip when the effect is added.
- *
- * @return The filepath of the generated image clip (null if it does not
- * exist)
- */
- String getGeneratedImageClip() {
- return mGeneratedImageClip;
- }
-
- /**
- * Find the effect with the specified id
- *
- * @param effectId The effect id
- * @return The effect with the specified id (null if it does not exist)
- */
- public Effect getEffect(String effectId) {
- for (Effect effect : mEffects) {
- if (effect.getId().equals(effectId)) {
- return effect;
- }
- }
- return null;
- }
-
- /**
- * Get the list of effects.
- *
- * @return the effects list. If no effects exist an empty list will be
- * returned.
- */
- public List<Effect> getAllEffects() {
- return mEffects;
- }
-
- /**
- * Add an overlay to the storyboard. This method invalidates a transition
- * video clip if the overlay overlaps with a transition.
- *
- * @param overlay The overlay to add
- * @throws IllegalStateException if a preview or an export is in progress or
- * if the overlay id is not unique across all the overlays added
- * or if the bitmap is not specified or if the dimensions of the
- * bitmap do not match the dimensions of the media item
- * @throws FileNotFoundException, IOException if overlay could not be saved
- * to project path
- */
- public void addOverlay(Overlay overlay) throws FileNotFoundException, IOException {
- if (overlay == null) {
- throw new IllegalArgumentException("NULL Overlay cannot be applied");
- }
-
- if (overlay.getMediaItem() != this) {
- throw new IllegalArgumentException("Media item mismatch");
- }
-
- if (mOverlays.contains(overlay)) {
- throw new IllegalArgumentException("Overlay already exists: " + overlay.getId());
- }
-
- if (overlay.getStartTime() + overlay.getDuration() > getDuration()) {
- throw new IllegalArgumentException(
- "Overlay start time + overlay duration > media clip duration");
- }
-
- if (overlay instanceof OverlayFrame) {
- final OverlayFrame frame = (OverlayFrame)overlay;
- final Bitmap bitmap = frame.getBitmap();
- if (bitmap == null) {
- throw new IllegalArgumentException("Overlay bitmap not specified");
- }
-
- final int scaledWidth, scaledHeight;
- if (this instanceof MediaVideoItem) {
- scaledWidth = getWidth();
- scaledHeight = getHeight();
- } else {
- scaledWidth = ((MediaImageItem)this).getScaledWidth();
- scaledHeight = ((MediaImageItem)this).getScaledHeight();
- }
-
- /**
- * The dimensions of the overlay bitmap must be the same as the
- * media item dimensions
- */
- if (bitmap.getWidth() != scaledWidth || bitmap.getHeight() != scaledHeight) {
- throw new IllegalArgumentException(
- "Bitmap dimensions must match media item dimensions");
- }
-
- mMANativeHelper.setGeneratePreview(true);
- ((OverlayFrame)overlay).save(mProjectPath);
-
- mOverlays.add(overlay);
- invalidateTransitions(overlay.getStartTime(), overlay.getDuration());
-
- } else {
- throw new IllegalArgumentException("Overlay not supported");
- }
- }
-
- /**
- * @param flag The flag to indicate if regeneration of clip is true or
- * false.
- */
- void setRegenerateClip(boolean flag) {
- mRegenerateClip = flag;
- }
-
- /**
- * @return flag The flag to indicate if regeneration of clip is true or
- * false.
- */
- boolean getRegenerateClip() {
- return mRegenerateClip;
- }
-
- /**
- * Remove the overlay with the specified id.
- *
- * This method invalidates a transition video clip if the overlay overlaps
- * with a transition.
- *
- * @param overlayId The id of the overlay to be removed
- *
- * @return The overlay that was removed
- * @throws IllegalStateException if a preview or an export is in progress
- */
- public Overlay removeOverlay(String overlayId) {
- for (Overlay overlay : mOverlays) {
- if (overlay.getId().equals(overlayId)) {
- mMANativeHelper.setGeneratePreview(true);
-
- mOverlays.remove(overlay);
- if (overlay instanceof OverlayFrame) {
- ((OverlayFrame)overlay).invalidate();
- }
- invalidateTransitions(overlay.getStartTime(), overlay.getDuration());
- return overlay;
- }
- }
- return null;
- }
-
- /**
- * Find the overlay with the specified id
- *
- * @param overlayId The overlay id
- *
- * @return The overlay with the specified id (null if it does not exist)
- */
- public Overlay getOverlay(String overlayId) {
- for (Overlay overlay : mOverlays) {
- if (overlay.getId().equals(overlayId)) {
- return overlay;
- }
- }
-
- return null;
- }
-
- /**
- * Get the list of overlays associated with this media item
- *
- * Note that if any overlay source files are not accessible anymore,
- * this method will still provide the full list of overlays.
- *
- * @return The list of overlays. If no overlays exist an empty list will
- * be returned.
- */
- public List<Overlay> getAllOverlays() {
- return mOverlays;
- }
-
- /**
- * Create a thumbnail at specified time in a video stream in Bitmap format
- *
- * @param width width of the thumbnail in pixels
- * @param height height of the thumbnail in pixels
- * @param timeMs The time in the source video file at which the thumbnail is
- * requested (even if trimmed).
- *
- * @return The thumbnail as a Bitmap.
- *
- * @throws IOException if a file error occurs
- * @throws IllegalArgumentException if time is out of video duration
- */
- public abstract Bitmap getThumbnail(int width, int height, long timeMs)
- throws IOException;
-
- /**
- * Get the array of Bitmap thumbnails between start and end.
- *
- * @param width width of the thumbnail in pixels
- * @param height height of the thumbnail in pixels
- * @param startMs The start of time range in milliseconds
- * @param endMs The end of the time range in milliseconds
- * @param thumbnailCount The thumbnail count
- * @param indices The indices of the thumbnails wanted
- * @param callback The callback used to pass back the bitmaps
- *
- * @throws IOException if a file error occurs
- */
- public abstract void getThumbnailList(int width, int height,
- long startMs, long endMs,
- int thumbnailCount,
- int[] indices,
- GetThumbnailListCallback callback)
- throws IOException;
-
- public interface GetThumbnailListCallback {
- public void onThumbnail(Bitmap bitmap, int index);
- }
-
- // This is for compatibility, only used in tests.
- public Bitmap[] getThumbnailList(int width, int height,
- long startMs, long endMs,
- int thumbnailCount)
- throws IOException {
- final Bitmap[] bitmaps = new Bitmap[thumbnailCount];
- int[] indices = new int[thumbnailCount];
- for (int i = 0; i < thumbnailCount; i++) {
- indices[i] = i;
- }
- getThumbnailList(width, height, startMs, endMs,
- thumbnailCount, indices, new GetThumbnailListCallback() {
- public void onThumbnail(Bitmap bitmap, int index) {
- bitmaps[index] = bitmap;
- }
- });
-
- return bitmaps;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof MediaItem)) {
- return false;
- }
- return mUniqueId.equals(((MediaItem)object).mUniqueId);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return mUniqueId.hashCode();
- }
-
- /**
- * Invalidate the start and end transitions if necessary
- *
- * @param startTimeMs The start time of the effect or overlay
- * @param durationMs The duration of the effect or overlay
- */
- abstract void invalidateTransitions(long startTimeMs, long durationMs);
-
- /**
- * Invalidate the start and end transitions if necessary. This method is
- * typically called when the start time and/or duration of an overlay or
- * effect is changing.
- *
- * @param oldStartTimeMs The old start time of the effect or overlay
- * @param oldDurationMs The old duration of the effect or overlay
- * @param newStartTimeMs The new start time of the effect or overlay
- * @param newDurationMs The new duration of the effect or overlay
- */
- abstract void invalidateTransitions(long oldStartTimeMs, long oldDurationMs,
- long newStartTimeMs, long newDurationMs);
-
- /**
- * Check if two items overlap in time
- *
- * @param startTimeMs1 Item 1 start time
- * @param durationMs1 Item 1 duration
- * @param startTimeMs2 Item 2 start time
- * @param durationMs2 Item 2 end time
- * @return true if the two items overlap
- */
- protected boolean isOverlapping(long startTimeMs1, long durationMs1,
- long startTimeMs2, long durationMs2) {
- if (startTimeMs1 + durationMs1 <= startTimeMs2) {
- return false;
- } else if (startTimeMs1 >= startTimeMs2 + durationMs2) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Adjust the duration transitions.
- */
- protected void adjustTransitions() {
- /**
- * Check if the duration of transitions need to be adjusted
- */
- if (mBeginTransition != null) {
- final long maxDurationMs = mBeginTransition.getMaximumDuration();
- if (mBeginTransition.getDuration() > maxDurationMs) {
- mBeginTransition.setDuration(maxDurationMs);
- }
- }
-
- if (mEndTransition != null) {
- final long maxDurationMs = mEndTransition.getMaximumDuration();
- if (mEndTransition.getDuration() > maxDurationMs) {
- mEndTransition.setDuration(maxDurationMs);
- }
- }
- }
-
- /**
- * @return MediaArtistNativeHleper context
- */
- MediaArtistNativeHelper getNativeContext() {
- return mMANativeHelper;
- }
-
- /**
- * Initialises ClipSettings fields to default value
- *
- * @param ClipSettings object
- *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
- */
- void initClipSettings(ClipSettings clipSettings) {
- clipSettings.clipPath = null;
- clipSettings.clipDecodedPath = null;
- clipSettings.clipOriginalPath = null;
- clipSettings.fileType = 0;
- clipSettings.endCutTime = 0;
- clipSettings.beginCutTime = 0;
- clipSettings.beginCutPercent = 0;
- clipSettings.endCutPercent = 0;
- clipSettings.panZoomEnabled = false;
- clipSettings.panZoomPercentStart = 0;
- clipSettings.panZoomTopLeftXStart = 0;
- clipSettings.panZoomTopLeftYStart = 0;
- clipSettings.panZoomPercentEnd = 0;
- clipSettings.panZoomTopLeftXEnd = 0;
- clipSettings.panZoomTopLeftYEnd = 0;
- clipSettings.mediaRendering = 0;
- clipSettings.rgbWidth = 0;
- clipSettings.rgbHeight = 0;
- }
-
- /**
- * @return ClipSettings object with populated data
- *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
- */
- ClipSettings getClipSettings() {
- MediaVideoItem mVI = null;
- MediaImageItem mII = null;
- ClipSettings clipSettings = new ClipSettings();
- initClipSettings(clipSettings);
- if (this instanceof MediaVideoItem) {
- mVI = (MediaVideoItem)this;
- clipSettings.clipPath = mVI.getFilename();
- clipSettings.fileType = mMANativeHelper.getMediaItemFileType(mVI.
- getFileType());
- clipSettings.beginCutTime = (int)mVI.getBoundaryBeginTime();
- clipSettings.endCutTime = (int)mVI.getBoundaryEndTime();
- clipSettings.mediaRendering = mMANativeHelper.
- getMediaItemRenderingMode(mVI
- .getRenderingMode());
- } else if (this instanceof MediaImageItem) {
- mII = (MediaImageItem)this;
- clipSettings = mII.getImageClipProperties();
- }
- return clipSettings;
- }
-
- /**
- * Generates a black frame to be used for generating
- * begin transition at first media item in storyboard
- * or end transition at last media item in storyboard
- *
- * @param ClipSettings object
- *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
- */
- void generateBlankFrame(ClipSettings clipSettings) {
- if (!mBlankFrameGenerated) {
- int mWidth = 64;
- int mHeight = 64;
- mBlankFrameFilename = String.format(mProjectPath + "/" + "ghost.rgb");
- FileOutputStream fl = null;
- try {
- fl = new FileOutputStream(mBlankFrameFilename);
- } catch (IOException e) {
- /* catch IO exception */
- }
- final DataOutputStream dos = new DataOutputStream(fl);
-
- final int [] framingBuffer = new int[mWidth];
-
- ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
- IntBuffer intBuffer;
-
- byte[] array = byteBuffer.array();
- int tmp = 0;
- while(tmp < mHeight) {
- intBuffer = byteBuffer.asIntBuffer();
- intBuffer.put(framingBuffer,0,mWidth);
- try {
- dos.write(array);
- } catch (IOException e) {
- /* catch file write error */
- }
- tmp += 1;
- }
-
- try {
- fl.close();
- } catch (IOException e) {
- /* file close error */
- }
- mBlankFrameGenerated = true;
- }
-
- clipSettings.clipPath = mBlankFrameFilename;
- clipSettings.fileType = FileType.JPG;
- clipSettings.beginCutTime = 0;
- clipSettings.endCutTime = 0;
- clipSettings.mediaRendering = MediaRendering.RESIZING;
-
- clipSettings.rgbWidth = 64;
- clipSettings.rgbHeight = 64;
- }
-
- /**
- * Invalidates the blank frame generated
- */
- void invalidateBlankFrame() {
- if (mBlankFrameFilename != null) {
- if (new File(mBlankFrameFilename).exists()) {
- new File(mBlankFrameFilename).delete();
- mBlankFrameFilename = null;
- }
- }
- }
-
-}
diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java
deleted file mode 100644
index cf518a5..0000000
--- a/media/java/android/media/videoeditor/MediaProperties.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-import android.media.videoeditor.VideoEditorProfile;
-import android.util.Pair;
-import java.lang.System;
-/**
- * This class defines all properties of a media file such as supported height,
- * aspect ratio, bitrate for export function.
- * {@hide}
- */
-public class MediaProperties {
- /**
- * Supported heights
- */
- public static final int HEIGHT_144 = 144;
- public static final int HEIGHT_288 = 288;
- public static final int HEIGHT_360 = 360;
- public static final int HEIGHT_480 = 480;
- public static final int HEIGHT_720 = 720;
- public static final int HEIGHT_1080 = 1080;
-
- /**
- * Supported aspect ratios
- */
- public static final int ASPECT_RATIO_UNDEFINED = 0;
- public static final int ASPECT_RATIO_3_2 = 1;
- public static final int ASPECT_RATIO_16_9 = 2;
- public static final int ASPECT_RATIO_4_3 = 3;
- public static final int ASPECT_RATIO_5_3 = 4;
- public static final int ASPECT_RATIO_11_9 = 5;
-
- /**
- * The array of supported aspect ratios
- */
- private static final int[] ASPECT_RATIOS = new int[] {
- ASPECT_RATIO_3_2,
- ASPECT_RATIO_16_9,
- ASPECT_RATIO_4_3,
- ASPECT_RATIO_5_3,
- ASPECT_RATIO_11_9
- };
-
- /**
- * Supported resolutions for specific aspect ratios
- */
- @SuppressWarnings({"unchecked"})
- private static final Pair<Integer, Integer>[] ASPECT_RATIO_3_2_RESOLUTIONS =
- new Pair[] {
- new Pair<Integer, Integer>(720, HEIGHT_480),
- new Pair<Integer, Integer>(1080, HEIGHT_720)
- };
-
- @SuppressWarnings({"unchecked"})
- private static final Pair<Integer, Integer>[] ASPECT_RATIO_4_3_RESOLUTIONS =
- new Pair[] {
- new Pair<Integer, Integer>(640, HEIGHT_480),
- new Pair<Integer, Integer>(960, HEIGHT_720)
- };
-
- @SuppressWarnings({"unchecked"})
- private static final Pair<Integer, Integer>[] ASPECT_RATIO_5_3_RESOLUTIONS =
- new Pair[] {
- new Pair<Integer, Integer>(800, HEIGHT_480)
- };
-
- @SuppressWarnings({"unchecked"})
- private static final Pair<Integer, Integer>[] ASPECT_RATIO_11_9_RESOLUTIONS =
- new Pair[] {
- new Pair<Integer, Integer>(176, HEIGHT_144),
- new Pair<Integer, Integer>(352, HEIGHT_288)
- };
-
- @SuppressWarnings({"unchecked"})
- private static final Pair<Integer, Integer>[] ASPECT_RATIO_16_9_RESOLUTIONS =
- new Pair[] {
- new Pair<Integer, Integer>(848, HEIGHT_480),
- new Pair<Integer, Integer>(1280, HEIGHT_720),
- new Pair<Integer, Integer>(1920, HEIGHT_1080),
- };
-
- /**
- * Bitrate values (in bits per second)
- */
- public static final int BITRATE_28K = 28000;
- public static final int BITRATE_40K = 40000;
- public static final int BITRATE_64K = 64000;
- public static final int BITRATE_96K = 96000;
- public static final int BITRATE_128K = 128000;
- public static final int BITRATE_192K = 192000;
- public static final int BITRATE_256K = 256000;
- public static final int BITRATE_384K = 384000;
- public static final int BITRATE_512K = 512000;
- public static final int BITRATE_800K = 800000;
- public static final int BITRATE_2M = 2000000;
- public static final int BITRATE_5M = 5000000;
- public static final int BITRATE_8M = 8000000;
-
- /**
- * The array of supported bitrates
- */
- private static final int[] SUPPORTED_BITRATES = new int[] {
- BITRATE_28K,
- BITRATE_40K,
- BITRATE_64K,
- BITRATE_96K,
- BITRATE_128K,
- BITRATE_192K,
- BITRATE_256K,
- BITRATE_384K,
- BITRATE_512K,
- BITRATE_800K,
- BITRATE_2M,
- BITRATE_5M,
- BITRATE_8M
- };
-
- /**
- * Video codec types
- */
- public static final int VCODEC_H263 = 1;
- public static final int VCODEC_H264 = 2;
- public static final int VCODEC_MPEG4 = 3;
-
- /**
- * The array of supported video codecs
- */
- private static final int[] SUPPORTED_VCODECS = new int[] {
- VCODEC_H264,
- VCODEC_H263,
- VCODEC_MPEG4,
- };
-
- /**
- * The H264 profile, the values are same as the one in OMX_Video.h
- */
- public final class H264Profile {
- public static final int H264ProfileBaseline = 0x01; /**< Baseline profile */
- public static final int H264ProfileMain = 0x02; /**< Main profile */
- public static final int H264ProfileExtended = 0x04; /**< Extended profile */
- public static final int H264ProfileHigh = 0x08; /**< High profile */
- public static final int H264ProfileHigh10 = 0x10; /**< High 10 profile */
- public static final int H264ProfileHigh422 = 0x20; /**< High 4:2:2 profile */
- public static final int H264ProfileHigh444 = 0x40; /**< High 4:4:4 profile */
- public static final int H264ProfileUnknown = 0x7FFFFFFF;
- }
- /**
- * The H264 level, the values are same as the one in OMX_Video.h
- */
- public final class H264Level {
- public static final int H264Level1 = 0x01; /**< Level 1 */
- public static final int H264Level1b = 0x02; /**< Level 1b */
- public static final int H264Level11 = 0x04; /**< Level 1.1 */
- public static final int H264Level12 = 0x08; /**< Level 1.2 */
- public static final int H264Level13 = 0x10; /**< Level 1.3 */
- public static final int H264Level2 = 0x20; /**< Level 2 */
- public static final int H264Level21 = 0x40; /**< Level 2.1 */
- public static final int H264Level22 = 0x80; /**< Level 2.2 */
- public static final int H264Level3 = 0x100; /**< Level 3 */
- public static final int H264Level31 = 0x200; /**< Level 3.1 */
- public static final int H264Level32 = 0x400; /**< Level 3.2 */
- public static final int H264Level4 = 0x800; /**< Level 4 */
- public static final int H264Level41 = 0x1000; /**< Level 4.1 */
- public static final int H264Level42 = 0x2000; /**< Level 4.2 */
- public static final int H264Level5 = 0x4000; /**< Level 5 */
- public static final int H264Level51 = 0x8000; /**< Level 5.1 */
- public static final int H264LevelUnknown = 0x7FFFFFFF;
- }
- /**
- * The H263 profile, the values are same as the one in OMX_Video.h
- */
- public final class H263Profile {
- public static final int H263ProfileBaseline = 0x01;
- public static final int H263ProfileH320Coding = 0x02;
- public static final int H263ProfileBackwardCompatible = 0x04;
- public static final int H263ProfileISWV2 = 0x08;
- public static final int H263ProfileISWV3 = 0x10;
- public static final int H263ProfileHighCompression = 0x20;
- public static final int H263ProfileInternet = 0x40;
- public static final int H263ProfileInterlace = 0x80;
- public static final int H263ProfileHighLatency = 0x100;
- public static final int H263ProfileUnknown = 0x7FFFFFFF;
- }
- /**
- * The H263 level, the values are same as the one in OMX_Video.h
- */
- public final class H263Level {
- public static final int H263Level10 = 0x01;
- public static final int H263Level20 = 0x02;
- public static final int H263Level30 = 0x04;
- public static final int H263Level40 = 0x08;
- public static final int H263Level45 = 0x10;
- public static final int H263Level50 = 0x20;
- public static final int H263Level60 = 0x40;
- public static final int H263Level70 = 0x80;
- public static final int H263LevelUnknown = 0x7FFFFFFF;
- }
- /**
- * The mpeg4 profile, the values are same as the one in OMX_Video.h
- */
- public final class MPEG4Profile {
- public static final int MPEG4ProfileSimple = 0x01;
- public static final int MPEG4ProfileSimpleScalable = 0x02;
- public static final int MPEG4ProfileCore = 0x04;
- public static final int MPEG4ProfileMain = 0x08;
- public static final int MPEG4ProfileNbit = 0x10;
- public static final int MPEG4ProfileScalableTexture = 0x20;
- public static final int MPEG4ProfileSimpleFace = 0x40;
- public static final int MPEG4ProfileSimpleFBA = 0x80;
- public static final int MPEG4ProfileBasicAnimated = 0x100;
- public static final int MPEG4ProfileHybrid = 0x200;
- public static final int MPEG4ProfileAdvancedRealTime = 0x400;
- public static final int MPEG4ProfileCoreScalable = 0x800;
- public static final int MPEG4ProfileAdvancedCoding = 0x1000;
- public static final int MPEG4ProfileAdvancedCore = 0x2000;
- public static final int MPEG4ProfileAdvancedScalable = 0x4000;
- public static final int MPEG4ProfileAdvancedSimple = 0x8000;
- public static final int MPEG4ProfileUnknown = 0x7FFFFFFF;
- }
- /**
- * The mpeg4 level, the values are same as the one in OMX_Video.h
- */
- public final class MPEG4Level {
- public static final int MPEG4Level0 = 0x01; /**< Level 0 */
- public static final int MPEG4Level0b = 0x02; /**< Level 0b */
- public static final int MPEG4Level1 = 0x04; /**< Level 1 */
- public static final int MPEG4Level2 = 0x08; /**< Level 2 */
- public static final int MPEG4Level3 = 0x10; /**< Level 3 */
- public static final int MPEG4Level4 = 0x20; /**< Level 4 */
- public static final int MPEG4Level4a = 0x40; /**< Level 4a */
- public static final int MPEG4Level5 = 0x80; /**< Level 5 */
- public static final int MPEG4LevelUnknown = 0x7FFFFFFF;
- }
- /**
- * Audio codec types
- */
- public static final int ACODEC_NO_AUDIO = 0;
- public static final int ACODEC_AMRNB = 1;
- public static final int ACODEC_AAC_LC = 2;
- public static final int ACODEC_AAC_PLUS = 3;
- public static final int ACODEC_ENHANCED_AAC_PLUS = 4;
- public static final int ACODEC_MP3 = 5;
- public static final int ACODEC_EVRC = 6;
- // 7 value is used for PCM
- public static final int ACODEC_AMRWB = 8;
- public static final int ACODEC_OGG = 9;
-
- /**
- * The array of supported audio codecs
- */
- private static final int[] SUPPORTED_ACODECS = new int[] {
- ACODEC_AAC_LC,
- ACODEC_AMRNB,
- ACODEC_AMRWB
- };
-
- /**
- * Samples per frame for each audio codec
- */
- public static final int SAMPLES_PER_FRAME_AAC = 1024;
- public static final int SAMPLES_PER_FRAME_MP3 = 1152;
- public static final int SAMPLES_PER_FRAME_AMRNB = 160;
- public static final int SAMPLES_PER_FRAME_AMRWB = 320;
-
- public static final int DEFAULT_SAMPLING_FREQUENCY = 32000;
- public static final int DEFAULT_CHANNEL_COUNT = 2;
-
- /**
- * File format types
- */
- public static final int FILE_3GP = 0;
- public static final int FILE_MP4 = 1;
- public static final int FILE_AMR = 2;
- public static final int FILE_MP3 = 3;
- // 4 is for PCM
- public static final int FILE_JPEG = 5;
- // 6 is for BMP
- // 7 is for GIF
- public static final int FILE_PNG = 8;
- // 9 is for ARGB8888
- public static final int FILE_M4V = 10;
- public static final int FILE_UNSUPPORTED = 255;
-
- /**
- * Undefined video codec profiles
- */
- public static final int UNDEFINED_VIDEO_PROFILE = 255;
-
- /**
- * The array of the supported file formats
- */
- private static final int[] SUPPORTED_VIDEO_FILE_FORMATS = new int[] {
- FILE_3GP,
- FILE_MP4,
- FILE_M4V
- };
-
- /**
- * The maximum count of audio tracks supported
- */
- public static final int AUDIO_MAX_TRACK_COUNT = 1;
-
- /** The maximum volume supported (100 means that no amplification is
- * supported, i.e. attenuation only)
- */
- public static final int AUDIO_MAX_VOLUME_PERCENT = 100;
-
- /**
- * This class cannot be instantiated
- */
- private MediaProperties() {
- }
-
- /**
- * @return The array of supported aspect ratios
- */
- public static int[] getAllSupportedAspectRatios() {
- return ASPECT_RATIOS;
- }
-
- /**
- * Get the supported resolutions for the specified aspect ratio.
- *
- * @param aspectRatio The aspect ratio for which the resolutions are
- * requested
- * @return The array of width and height pairs
- */
- public static Pair<Integer, Integer>[] getSupportedResolutions(int aspectRatio) {
- final Pair<Integer, Integer>[] resolutions;
- switch (aspectRatio) {
- case ASPECT_RATIO_3_2: {
- resolutions = ASPECT_RATIO_3_2_RESOLUTIONS;
- break;
- }
-
- case ASPECT_RATIO_4_3: {
- resolutions = ASPECT_RATIO_4_3_RESOLUTIONS;
- break;
- }
-
- case ASPECT_RATIO_5_3: {
- resolutions = ASPECT_RATIO_5_3_RESOLUTIONS;
- break;
- }
-
- case ASPECT_RATIO_11_9: {
- resolutions = ASPECT_RATIO_11_9_RESOLUTIONS;
- break;
- }
-
- case ASPECT_RATIO_16_9: {
- resolutions = ASPECT_RATIO_16_9_RESOLUTIONS;
- break;
- }
-
- default: {
- throw new IllegalArgumentException("Unknown aspect ratio: " + aspectRatio);
- }
- }
-
- /** Check the platform specific maximum export resolution */
- VideoEditorProfile veProfile = VideoEditorProfile.get();
- if (veProfile == null) {
- throw new RuntimeException("Can't get the video editor profile");
- }
- final int maxWidth = veProfile.maxOutputVideoFrameWidth;
- final int maxHeight = veProfile.maxOutputVideoFrameHeight;
- Pair<Integer, Integer>[] tmpResolutions = new Pair[resolutions.length];
- int numSupportedResolution = 0;
- int i = 0;
-
- /** Get supported resolution list */
- for (i = 0; i < resolutions.length; i++) {
- if ((resolutions[i].first <= maxWidth) &&
- (resolutions[i].second <= maxHeight)) {
- tmpResolutions[numSupportedResolution] = resolutions[i];
- numSupportedResolution++;
- }
- }
- final Pair<Integer, Integer>[] supportedResolutions =
- new Pair[numSupportedResolution];
- System.arraycopy(tmpResolutions, 0,
- supportedResolutions, 0, numSupportedResolution);
-
- return supportedResolutions;
- }
-
- /**
- * @return The array of supported video codecs
- */
- public static int[] getSupportedVideoCodecs() {
- return SUPPORTED_VCODECS;
- }
-
- /**
- * @return The array of supported audio codecs
- */
- public static int[] getSupportedAudioCodecs() {
- return SUPPORTED_ACODECS;
- }
-
- /**
- * @return The array of supported file formats
- */
- public static int[] getSupportedVideoFileFormat() {
- return SUPPORTED_VIDEO_FILE_FORMATS;
- }
-
- /**
- * @return The array of supported video bitrates
- */
- public static int[] getSupportedVideoBitrates() {
- return SUPPORTED_BITRATES;
- }
-
- /**
- * @return The maximum value for the audio volume
- */
- public static int getSupportedMaxVolume() {
- return MediaProperties.AUDIO_MAX_VOLUME_PERCENT;
- }
-
- /**
- * @return The maximum number of audio tracks supported
- */
- public static int getSupportedAudioTrackCount() {
- return MediaProperties.AUDIO_MAX_TRACK_COUNT;
- }
-}
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
deleted file mode 100644
index bbcdf57..0000000
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-import android.media.videoeditor.VideoEditorProfile;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-/**
- * This class represents a video clip item on the storyboard
- * {@hide}
- */
-public class MediaVideoItem extends MediaItem {
-
- /**
- * Instance variables
- */
- private final int mWidth;
- private final int mHeight;
- private final int mAspectRatio;
- private final int mFileType;
- private final int mVideoType;
- private final int mVideoProfile;
- private final int mVideoLevel;
- private final int mVideoBitrate;
- private final long mDurationMs;
- private final int mAudioBitrate;
- private final int mFps;
- private final int mAudioType;
- private final int mAudioChannels;
- private final int mAudioSamplingFrequency;
- private long mBeginBoundaryTimeMs;
- private long mEndBoundaryTimeMs;
- private int mVolumePercentage;
- private boolean mMuted;
- private String mAudioWaveformFilename;
- private MediaArtistNativeHelper mMANativeHelper;
- private VideoEditorImpl mVideoEditor;
- private final int mVideoRotationDegree;
- /**
- * The audio waveform data
- */
- private SoftReference<WaveformData> mWaveformData;
-
- /**
- * An object of this type cannot be instantiated with a default constructor
- */
- @SuppressWarnings("unused")
- private MediaVideoItem() throws IOException {
- this(null, null, null, RENDERING_MODE_BLACK_BORDER);
- }
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param mediaItemId The MediaItem id
- * @param filename The image file name
- * @param renderingMode The rendering mode
- *
- * @throws IOException if the file cannot be opened for reading
- */
- public MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
- int renderingMode) throws IOException {
- this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null);
- }
-
- /**
- * Constructor
- *
- * @param editor The video editor reference
- * @param mediaItemId The MediaItem id
- * @param filename The image file name
- * @param renderingMode The rendering mode
- * @param beginMs Start time in milliseconds. Set to 0 to extract from the
- * beginning
- * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
- * extract until the end
- * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
- * means double, 0% means silent.
- * @param muted true if the audio is muted
- * @param audioWaveformFilename The name of the audio waveform file
- *
- * @throws IOException if the file cannot be opened for reading
- */
- MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
- int renderingMode, long beginMs, long endMs, int volumePercent, boolean muted,
- String audioWaveformFilename) throws IOException {
- super(editor, mediaItemId, filename, renderingMode);
-
- if (editor instanceof VideoEditorImpl) {
- mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
- mVideoEditor = ((VideoEditorImpl)editor);
- }
-
- final Properties properties;
- try {
- properties = mMANativeHelper.getMediaProperties(filename);
- } catch ( Exception e) {
- throw new IllegalArgumentException(e.getMessage() + " : " + filename);
- }
-
- /** Check the platform specific maximum import resolution */
- VideoEditorProfile veProfile = VideoEditorProfile.get();
- if (veProfile == null) {
- throw new RuntimeException("Can't get the video editor profile");
- }
- final int maxInputWidth = veProfile.maxInputVideoFrameWidth;
- final int maxInputHeight = veProfile.maxInputVideoFrameHeight;
- if ((properties.width > maxInputWidth) ||
- (properties.height > maxInputHeight)) {
- throw new IllegalArgumentException(
- "Unsupported import resolution. Supported maximum width:" +
- maxInputWidth + " height:" + maxInputHeight +
- ", current width:" + properties.width +
- " height:" + properties.height);
- }
- /** Check the platform specific maximum video profile and level */
- if (!properties.profileSupported) {
- throw new IllegalArgumentException(
- "Unsupported video profile " + properties.profile);
- }
- if (!properties.levelSupported) {
- throw new IllegalArgumentException(
- "Unsupported video level " + properties.level);
- }
- switch (mMANativeHelper.getFileType(properties.fileType)) {
- case MediaProperties.FILE_3GP:
- case MediaProperties.FILE_MP4:
- case MediaProperties.FILE_M4V:
- break;
-
- default:
- throw new IllegalArgumentException("Unsupported Input File Type");
- }
-
- switch (mMANativeHelper.getVideoCodecType(properties.videoFormat)) {
- case MediaProperties.VCODEC_H263:
- case MediaProperties.VCODEC_H264:
- case MediaProperties.VCODEC_MPEG4:
- break;
-
- default:
- throw new IllegalArgumentException("Unsupported Video Codec Format in Input File");
- }
-
- mWidth = properties.width;
- mHeight = properties.height;
- mAspectRatio = mMANativeHelper.getAspectRatio(properties.width,
- properties.height);
- mFileType = mMANativeHelper.getFileType(properties.fileType);
- mVideoType = mMANativeHelper.getVideoCodecType(properties.videoFormat);
- mVideoProfile = properties.profile;
- mVideoLevel = properties.level;
- mDurationMs = properties.videoDuration;
- mVideoBitrate = properties.videoBitrate;
- mAudioBitrate = properties.audioBitrate;
- mFps = (int)properties.averageFrameRate;
- mAudioType = mMANativeHelper.getAudioCodecType(properties.audioFormat);
- mAudioChannels = properties.audioChannels;
- mAudioSamplingFrequency = properties.audioSamplingFrequency;
- mBeginBoundaryTimeMs = beginMs;
- mEndBoundaryTimeMs = endMs == END_OF_FILE ? mDurationMs : endMs;
- mVolumePercentage = volumePercent;
- mMuted = muted;
- mAudioWaveformFilename = audioWaveformFilename;
- if (audioWaveformFilename != null) {
- mWaveformData = new SoftReference<WaveformData>(
- new WaveformData(audioWaveformFilename));
- } else {
- mWaveformData = null;
- }
- mVideoRotationDegree = properties.videoRotation;
- }
-
- /**
- * Sets the start and end marks for trimming a video media item.
- * This method will adjust the duration of bounding transitions, effects
- * and overlays if the current duration of the transactions become greater
- * than the maximum allowable duration.
- *
- * @param beginMs Start time in milliseconds. Set to 0 to extract from the
- * beginning
- * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
- * extract until the end
- *
- * @throws IllegalArgumentException if the start time is greater or equal than
- * end time, the end time is beyond the file duration, the start time
- * is negative
- */
- public void setExtractBoundaries(long beginMs, long endMs) {
- if (beginMs > mDurationMs) {
- throw new IllegalArgumentException("setExtractBoundaries: Invalid start time");
- }
-
- if (endMs > mDurationMs) {
- throw new IllegalArgumentException("setExtractBoundaries: Invalid end time");
- }
-
- if ((endMs != -1) && (beginMs >= endMs) ) {
- throw new IllegalArgumentException("setExtractBoundaries: Start time is greater than end time");
- }
-
- if ((beginMs < 0) || ((endMs != -1) && (endMs < 0))) {
- throw new IllegalArgumentException("setExtractBoundaries: Start time or end time is negative");
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- if (beginMs != mBeginBoundaryTimeMs) {
- if (mBeginTransition != null) {
- mBeginTransition.invalidate();
- }
- }
-
- if (endMs != mEndBoundaryTimeMs) {
- if (mEndTransition != null) {
- mEndTransition.invalidate();
- }
- }
-
- mBeginBoundaryTimeMs = beginMs;
- mEndBoundaryTimeMs = endMs;
- adjustTransitions();
- mVideoEditor.updateTimelineDuration();
- /**
- * Note that the start and duration of any effects and overlays are
- * not adjusted nor are they automatically removed if they fall
- * outside the new boundaries.
- */
- }
-
- /**
- * @return The boundary begin time
- */
- public long getBoundaryBeginTime() {
- return mBeginBoundaryTimeMs;
- }
-
- /**
- * @return The boundary end time
- */
- public long getBoundaryEndTime() {
- return mEndBoundaryTimeMs;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public void addEffect(Effect effect) {
- if (effect instanceof EffectKenBurns) {
- throw new IllegalArgumentException("Ken Burns effects cannot be applied to MediaVideoItem");
- }
- super.addEffect(effect);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public Bitmap getThumbnail(int width, int height, long timeMs) {
- if (timeMs > mDurationMs) {
- throw new IllegalArgumentException("Time Exceeds duration");
- }
-
- if (timeMs < 0) {
- throw new IllegalArgumentException("Invalid Time duration");
- }
-
- if ((width <= 0) || (height <= 0)) {
- throw new IllegalArgumentException("Invalid Dimensions");
- }
-
- if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
- int temp = width;
- width = height;
- height = temp;
- }
-
- return mMANativeHelper.getPixels(
- getFilename(), width, height, timeMs, mVideoRotationDegree);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public void getThumbnailList(int width, int height,
- long startMs, long endMs,
- int thumbnailCount,
- int[] indices,
- GetThumbnailListCallback callback)
- throws IOException {
- if (startMs > endMs) {
- throw new IllegalArgumentException("Start time is greater than end time");
- }
-
- if (endMs > mDurationMs) {
- throw new IllegalArgumentException("End time is greater than file duration");
- }
-
- if ((height <= 0) || (width <= 0)) {
- throw new IllegalArgumentException("Invalid dimension");
- }
-
- if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
- int temp = width;
- width = height;
- height = temp;
- }
-
- mMANativeHelper.getPixelsList(getFilename(), width, height,
- startMs, endMs, thumbnailCount, indices, callback,
- mVideoRotationDegree);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void invalidateTransitions(long startTimeMs, long durationMs) {
- /**
- * Check if the item overlaps with the beginning and end transitions
- */
- if (mBeginTransition != null) {
- if (isOverlapping(startTimeMs, durationMs,
- mBeginBoundaryTimeMs, mBeginTransition.getDuration())) {
- mBeginTransition.invalidate();
- }
- }
-
- if (mEndTransition != null) {
- final long transitionDurationMs = mEndTransition.getDuration();
- if (isOverlapping(startTimeMs, durationMs,
- mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs)) {
- mEndTransition.invalidate();
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs,
- long newDurationMs) {
- /**
- * Check if the item overlaps with the beginning and end transitions
- */
- if (mBeginTransition != null) {
- final long transitionDurationMs = mBeginTransition.getDuration();
- final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
- mBeginBoundaryTimeMs, transitionDurationMs);
- final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
- mBeginBoundaryTimeMs, transitionDurationMs);
- /**
- * Invalidate transition if:
- *
- * 1. New item overlaps the transition, the old one did not
- * 2. New item does not overlap the transition, the old one did
- * 3. New and old item overlap the transition if begin or end
- * time changed
- */
- if (newOverlap != oldOverlap) { // Overlap has changed
- mBeginTransition.invalidate();
- } else if (newOverlap) { // Both old and new overlap
- if ((oldStartTimeMs != newStartTimeMs) ||
- !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
- newStartTimeMs + newDurationMs > transitionDurationMs)) {
- mBeginTransition.invalidate();
- }
- }
- }
-
- if (mEndTransition != null) {
- final long transitionDurationMs = mEndTransition.getDuration();
- final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
- mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
- final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
- mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
- /**
- * Invalidate transition if:
- *
- * 1. New item overlaps the transition, the old one did not
- * 2. New item does not overlap the transition, the old one did
- * 3. New and old item overlap the transition if begin or end
- * time changed
- */
- if (newOverlap != oldOverlap) { // Overlap has changed
- mEndTransition.invalidate();
- } else if (newOverlap) { // Both old and new overlap
- if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
- ((oldStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs) ||
- newStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs)) {
- mEndTransition.invalidate();
- }
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getAspectRatio() {
- return mAspectRatio;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getFileType() {
- return mFileType;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getWidth() {
- if (mVideoRotationDegree == 90 ||
- mVideoRotationDegree == 270) {
- return mHeight;
- } else {
- return mWidth;
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int getHeight() {
- if (mVideoRotationDegree == 90 ||
- mVideoRotationDegree == 270) {
- return mWidth;
- } else {
- return mHeight;
- }
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public long getDuration() {
- return mDurationMs;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public long getTimelineDuration() {
- return mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
- }
-
- /**
- * Render a frame according to the playback (in the native aspect ratio) for
- * the specified media item. All effects and overlays applied to the media
- * item are ignored. The extract boundaries are also ignored. This method
- * can be used to playback frames when implementing trimming functionality.
- *
- * @param surfaceHolder SurfaceHolder used by the application
- * @param timeMs time corresponding to the frame to display (relative to the
- * the beginning of the media item).
- * @return The accurate time stamp of the frame that is rendered .
- * @throws IllegalStateException if a playback, preview or an export is
- * already in progress
- * @throws IllegalArgumentException if time is negative or greater than the
- * media item duration
- */
- public long renderFrame(SurfaceHolder surfaceHolder, long timeMs) {
- if (surfaceHolder == null) {
- throw new IllegalArgumentException("Surface Holder is null");
- }
-
- if (timeMs > mDurationMs || timeMs < 0) {
- throw new IllegalArgumentException("requested time not correct");
- }
-
- final Surface surface = surfaceHolder.getSurface();
- if (surface == null) {
- throw new RuntimeException("Surface could not be retrieved from Surface holder");
- }
-
- if (mFilename != null) {
- return mMANativeHelper.renderMediaItemPreviewFrame(surface,
- mFilename,timeMs,mWidth,mHeight);
- } else {
- return 0;
- }
- }
-
-
- /**
- * This API allows to generate a file containing the sample volume levels of
- * the Audio track of this media item. This function may take significant
- * time and is blocking. The file can be retrieved using
- * getAudioWaveformFilename().
- *
- * @param listener The progress listener
- *
- * @throws IOException if the output file cannot be created
- * @throws IllegalArgumentException if the mediaItem does not have a valid
- * Audio track
- */
- public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
- throws IOException {
- int frameDuration = 0;
- int sampleCount = 0;
- final String projectPath = mMANativeHelper.getProjectPath();
- /**
- * Waveform file does not exist
- */
- if (mAudioWaveformFilename == null ) {
- /**
- * Since audioWaveformFilename will not be supplied,it is generated
- */
- String mAudioWaveFileName = null;
-
- mAudioWaveFileName =
- String.format(projectPath + "/" + "audioWaveformFile-"+ getId() + ".dat");
- /**
- * Logic to get frame duration = (no. of frames per sample * 1000)/
- * sampling frequency
- */
- if (mMANativeHelper.getAudioCodecType(mAudioType) ==
- MediaProperties.ACODEC_AMRNB ) {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB*1000)/
- MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB;
- } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
- MediaProperties.ACODEC_AMRWB ) {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)/
- MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB;
- } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
- MediaProperties.ACODEC_AAC_LC ) {
- frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)/
- MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
- sampleCount = MediaProperties.SAMPLES_PER_FRAME_AAC;
- }
-
- mMANativeHelper.generateAudioGraph( getId(),
- mFilename,
- mAudioWaveFileName,
- frameDuration,
- MediaProperties.DEFAULT_CHANNEL_COUNT,
- sampleCount,
- listener,
- true);
- /**
- * Record the generated file name
- */
- mAudioWaveformFilename = mAudioWaveFileName;
- }
- mWaveformData =
- new SoftReference<WaveformData>(new WaveformData(mAudioWaveformFilename));
- }
-
- /**
- * Get the audio waveform file name if {@link #extractAudioWaveform()} was
- * successful. The file format is as following:
- * <ul>
- * <li>first 4 bytes provide the number of samples for each value, as big-endian signed</li>
- * <li>4 following bytes is the total number of values in the file, as big-endian signed</li>
- * <li>all values follow as bytes Name is unique.</li>
- *</ul>
- * @return the name of the file, null if the file has not been computed or
- * if there is no Audio track in the mediaItem
- */
- String getAudioWaveformFilename() {
- return mAudioWaveformFilename;
- }
-
- /**
- * Invalidate the AudioWaveform File
- */
- void invalidate() {
- if (mAudioWaveformFilename != null) {
- new File(mAudioWaveformFilename).delete();
- mAudioWaveformFilename = null;
- }
- }
-
- /**
- * @return The waveform data
- */
- public WaveformData getWaveformData() throws IOException {
- if (mWaveformData == null) {
- return null;
- }
-
- WaveformData waveformData = mWaveformData.get();
- if (waveformData != null) {
- return waveformData;
- } else if (mAudioWaveformFilename != null) {
- try {
- waveformData = new WaveformData(mAudioWaveformFilename);
- } catch(IOException e) {
- throw e;
- }
- mWaveformData = new SoftReference<WaveformData>(waveformData);
- return waveformData;
- } else {
- return null;
- }
- }
-
- /**
- * Set volume of the Audio track of this mediaItem
- *
- * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
- * means double, 0% means silent.
- * @throws UsupportedOperationException if volume value is not supported
- */
- public void setVolume(int volumePercent) {
- if ((volumePercent <0) || (volumePercent >100)) {
- throw new IllegalArgumentException("Invalid volume");
- }
-
- mVolumePercentage = volumePercent;
- }
-
- /**
- * Get the volume value of the audio track as percentage. Call of this
- * method before calling setVolume will always return 100%
- *
- * @return the volume in percentage
- */
- public int getVolume() {
- return mVolumePercentage;
- }
-
- /**
- * @param muted true to mute the media item
- */
- public void setMute(boolean muted) {
- mMANativeHelper.setGeneratePreview(true);
- mMuted = muted;
- if (mBeginTransition != null) {
- mBeginTransition.invalidate();
- }
- if (mEndTransition != null) {
- mEndTransition.invalidate();
- }
- }
-
- /**
- * @return true if the media item is muted
- */
- public boolean isMuted() {
- return mMuted;
- }
-
- /**
- * @return The video type
- */
- public int getVideoType() {
- return mVideoType;
- }
-
- /**
- * @return The video profile
- */
- public int getVideoProfile() {
- return mVideoProfile;
- }
-
- /**
- * @return The video profile
- */
- public int getVideoLevel() {
- return mVideoLevel;
- }
-
- /**
- * @return The video bitrate
- */
- public int getVideoBitrate() {
- return mVideoBitrate;
- }
-
- /**
- * @return The audio bitrate
- */
- public int getAudioBitrate() {
- return mAudioBitrate;
- }
-
- /**
- * @return The number of frames per second
- */
- public int getFps() {
- return mFps;
- }
-
- /**
- * @return The audio codec
- */
- public int getAudioType() {
- return mAudioType;
- }
-
- /**
- * @return The number of audio channels
- */
- public int getAudioChannels() {
- return mAudioChannels;
- }
-
- /**
- * @return The audio sample frequency
- */
- public int getAudioSamplingFrequency() {
- return mAudioSamplingFrequency;
- }
-
- /**
- * @return The Video media item properties in ClipSettings class object
- * {@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
- */
- ClipSettings getVideoClipProperties() {
- ClipSettings clipSettings = new ClipSettings();
- clipSettings.clipPath = getFilename();
- clipSettings.fileType = mMANativeHelper.getMediaItemFileType(getFileType());
- clipSettings.beginCutTime = (int)getBoundaryBeginTime();
- clipSettings.endCutTime = (int)getBoundaryEndTime();
- clipSettings.mediaRendering = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
- clipSettings.rotationDegree = mVideoRotationDegree;
-
- return clipSettings;
- }
-}
diff --git a/media/java/android/media/videoeditor/Overlay.java b/media/java/android/media/videoeditor/Overlay.java
deleted file mode 100644
index a070eb4..0000000
--- a/media/java/android/media/videoeditor/Overlay.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * This is the super class for all Overlay classes.
- * {@hide}
- */
-public abstract class Overlay {
- /**
- * Instance variables
- */
- private final String mUniqueId;
- /**
- * The overlay owner
- */
- private final MediaItem mMediaItem;
- /**
- * user attributes
- */
- private final Map<String, String> mUserAttributes;
-
- protected long mStartTimeMs;
- protected long mDurationMs;
-
- /**
- * Default constructor
- */
- @SuppressWarnings("unused")
- private Overlay() {
- this(null, null, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param mediaItem The media item owner
- * @param overlayId The overlay id
- * @param startTimeMs The start time relative to the media item start time
- * @param durationMs The duration
- *
- * @throws IllegalArgumentException if the file type is not PNG or the
- * startTimeMs and durationMs are incorrect.
- */
- public Overlay(MediaItem mediaItem, String overlayId, long startTimeMs,
- long durationMs) {
- if (mediaItem == null) {
- throw new IllegalArgumentException("Media item cannot be null");
- }
-
- if ((startTimeMs<0) || (durationMs<0) ) {
- throw new IllegalArgumentException("Invalid start time and/OR duration");
- }
-
- if (startTimeMs + durationMs > mediaItem.getDuration()) {
- throw new IllegalArgumentException("Invalid start time and duration");
- }
-
- mMediaItem = mediaItem;
- mUniqueId = overlayId;
- mStartTimeMs = startTimeMs;
- mDurationMs = durationMs;
- mUserAttributes = new HashMap<String, String>();
- }
-
- /**
- * Get the overlay ID.
- *
- * @return The of the overlay
- */
- public String getId() {
- return mUniqueId;
- }
-
- /**
- * Get the duration of overlay.
- *
- * @return The duration of the overlay effect
- */
- public long getDuration() {
- return mDurationMs;
- }
-
- /**
- * If a preview or export is in progress, then this change is effective for
- * next preview or export session.
- *
- * @param durationMs The duration in milliseconds
- */
- public void setDuration(long durationMs) {
- if (durationMs < 0) {
- throw new IllegalArgumentException("Invalid duration");
- }
-
- if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Duration is too large");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
-
- final long oldDurationMs = mDurationMs;
- mDurationMs = durationMs;
-
- mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the start time of overlay.
- *
- * @return the start time of the overlay
- */
- public long getStartTime() {
- return mStartTimeMs;
- }
-
- /**
- * Set the start time for the overlay. If a preview or export is in
- * progress, then this change is effective for next preview or export
- * session.
- *
- * @param startTimeMs start time in milliseconds
- */
- public void setStartTime(long startTimeMs) {
- if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Start time is too large");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
-
- final long oldStartTimeMs = mStartTimeMs;
- mStartTimeMs = startTimeMs;
-
- mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Set the start time and duration
- *
- * @param startTimeMs start time in milliseconds
- * @param durationMs The duration in milliseconds
- */
- public void setStartTimeAndDuration(long startTimeMs, long durationMs) {
- if (startTimeMs + durationMs > mMediaItem.getDuration()) {
- throw new IllegalArgumentException("Invalid start time or duration");
- }
-
- getMediaItem().getNativeContext().setGeneratePreview(true);
-
- final long oldStartTimeMs = mStartTimeMs;
- final long oldDurationMs = mDurationMs;
-
- mStartTimeMs = startTimeMs;
- mDurationMs = durationMs;
-
- mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the media item owner.
- *
- * @return The media item owner.
- */
- public MediaItem getMediaItem() {
- return mMediaItem;
- }
-
- /**
- * Set a user attribute
- *
- * @param name The attribute name
- * @param value The attribute value
- */
- public void setUserAttribute(String name, String value) {
- mUserAttributes.put(name, value);
- }
-
- /**
- * Get the current user attributes set.
- *
- * @return The user attributes
- */
- public Map<String, String> getUserAttributes() {
- return mUserAttributes;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof Overlay)) {
- return false;
- }
- return mUniqueId.equals(((Overlay)object).mUniqueId);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return mUniqueId.hashCode();
- }
-}
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
deleted file mode 100644
index d159df2..0000000
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.DataOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap.CompressFormat;
-import android.util.Pair;
-
-
-/**
- * This class is used to overlay an image on top of a media item.
- * {@hide}
- */
-public class OverlayFrame extends Overlay {
- /**
- * Instance variables
- */
- private Bitmap mBitmap;
- private String mFilename;
- private String mBitmapFileName;
-
- private int mOFWidth;
- private int mOFHeight;
-
- /**
- * resized RGB Image dimensions
- */
- private int mResizedRGBWidth;
- private int mResizedRGBHeight;
-
- /**
- * The resize paint
- */
- private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private OverlayFrame() {
- this(null, null, (String)null, 0, 0);
- }
-
- /**
- * Constructor for an OverlayFrame
- *
- * @param mediaItem The media item owner
- * @param overlayId The overlay id
- * @param bitmap The bitmap to be used as an overlay. The size of the
- * bitmap must equal to the size of the media item to which it is
- * added. The bitmap is typically a decoded PNG file.
- * @param startTimeMs The overlay start time in milliseconds
- * @param durationMs The overlay duration in milliseconds
- *
- * @throws IllegalArgumentException if the file type is not PNG or the
- * startTimeMs and durationMs are incorrect.
- */
- public OverlayFrame(MediaItem mediaItem, String overlayId, Bitmap bitmap,
- long startTimeMs,long durationMs) {
- super(mediaItem, overlayId, startTimeMs, durationMs);
- mBitmap = bitmap;
- mFilename = null;
- mBitmapFileName = null;
- mResizedRGBWidth = 0;
- mResizedRGBHeight = 0;
- }
-
- /**
- * Constructor for an OverlayFrame. This constructor can be used to
- * restore the overlay after it was saved internally by the video editor.
- *
- * @param mediaItem The media item owner
- * @param overlayId The overlay id
- * @param filename The file name that contains the overlay.
- * @param startTimeMs The overlay start time in milliseconds
- * @param durationMs The overlay duration in milliseconds
- *
- * @throws IllegalArgumentException if the file type is not PNG or the
- * startTimeMs and durationMs are incorrect.
- */
- OverlayFrame(MediaItem mediaItem, String overlayId, String filename,
- long startTimeMs,long durationMs) {
- super(mediaItem, overlayId, startTimeMs, durationMs);
- mBitmapFileName = filename;
- mBitmap = BitmapFactory.decodeFile(mBitmapFileName);
- mFilename = null;
- mResizedRGBWidth = 0;
- mResizedRGBHeight = 0;
- }
-
- /**
- * Get the overlay bitmap.
- *
- * @return Get the overlay bitmap
- */
- public Bitmap getBitmap() {
- return mBitmap;
- }
-
- /**
- * Get the overlay bitmap.
- *
- * @return Get the overlay bitmap as png file.
- */
- String getBitmapImageFileName() {
- return mBitmapFileName;
- }
- /**
- * Set the overlay bitmap.
- *
- * @param bitmap The overlay bitmap.
- */
- public void setBitmap(Bitmap bitmap) {
- getMediaItem().getNativeContext().setGeneratePreview(true);
-
- invalidate();
-
- mBitmap = bitmap;
- if (mFilename != null) {
- /**
- * Delete the file
- */
- new File(mFilename).delete();
- /**
- * Invalidate the filename
- */
- mFilename = null;
- }
-
- /**
- * Invalidate the transitions if necessary
- */
- getMediaItem().invalidateTransitions(mStartTimeMs, mDurationMs);
- }
-
- /**
- * Get the file name of this overlay
- */
- String getFilename() {
- return mFilename;
- }
-
- /*
- * Set the file name of this overlay
- */
- void setFilename(String filename) {
- mFilename = filename;
- }
- /**
- * Save the overlay to the project folder
- *
- * @param path The path where the overlay will be saved
- *
- * @return The filename
- * @throws FileNotFoundException if the bitmap cannot be saved
- * @throws IOException if the bitmap file cannot be saved
- */
- String save(String path) throws FileNotFoundException, IOException {
- if (mFilename != null) {
- return mFilename;
- }
-
- // Create the compressed PNG file
- mBitmapFileName = path + "/" + "Overlay" + getId() + ".png";
- if (!(new File(mBitmapFileName).exists())) {
- final FileOutputStream out = new FileOutputStream (mBitmapFileName);
- mBitmap.compress(CompressFormat.PNG, 100, out);
- out.flush();
- out.close();
- }
-
- mOFWidth = mBitmap.getWidth();
- mOFHeight = mBitmap.getHeight();
-
- mFilename = path + "/" + "Overlay" + getId() + ".rgb";
-
- /* resize and save rgb as per project aspect ratio */
- MediaArtistNativeHelper nativeHelper = (super.getMediaItem()).getNativeContext();
-
- /* get height and width for story board aspect ratio */
- final Pair<Integer, Integer> maxResolution;
- final Pair<Integer, Integer>[] resolutions;
- resolutions = MediaProperties.getSupportedResolutions(nativeHelper.nativeHelperGetAspectRatio());
-
- // Get the highest resolution
- maxResolution = resolutions[resolutions.length - 1];
-
- /* Generate the rgb file with rendering mode */
- generateOverlayWithRenderingMode (super.getMediaItem(), this,
- maxResolution.second /* max Height */ ,
- maxResolution.first /* max Width */);
-
- return mFilename;
- }
-
- /**
- * Get the OverlayFrame Height
- */
- int getOverlayFrameHeight() {
- return mOFHeight;
- }
-
- /**
- * Get the OverlayFrame Width
- */
- int getOverlayFrameWidth() {
- return mOFWidth;
- }
-
- /*
- * Set the OverlayFrame Height
- */
- void setOverlayFrameHeight(int height) {
- mOFHeight = height;
- }
-
- /*
- * Set the OverlayFrame Width
- */
- void setOverlayFrameWidth(int width) {
- mOFWidth = width;
- }
-
- /*
- * Set the resized RGB widht and height
- */
- void setResizedRGBSize(int width, int height) {
- mResizedRGBWidth = width;
- mResizedRGBHeight = height;
- }
-
- /*
- * Get the resized RGB Height
- */
- int getResizedRGBSizeHeight() {
- return mResizedRGBHeight;
- }
-
- /*
- * Get the resized RGB Width
- */
- int getResizedRGBSizeWidth() {
- return mResizedRGBWidth;
- }
-
-
- /**
- * Delete the overlay files
- */
- void invalidate() {
- if (mBitmap != null) {
- mBitmap.recycle();
- mBitmap = null;
- }
-
- if (mFilename != null) {
- new File(mFilename).delete();
- mFilename = null;
- }
-
- if (mBitmapFileName != null) {
- new File(mBitmapFileName).delete();
- mBitmapFileName = null;
- }
- }
-
- /**
- * Delete the overlay related files
- */
- void invalidateGeneratedFiles() {
- if (mFilename != null) {
- new File(mFilename).delete();
- mFilename = null;
- }
-
- if (mBitmapFileName != null) {
- new File(mBitmapFileName).delete();
- mBitmapFileName = null;
- }
- }
-
- void generateOverlayWithRenderingMode (MediaItem mediaItemsList, OverlayFrame overlay, int height , int width)
- throws FileNotFoundException, IOException {
-
- final MediaItem t = mediaItemsList;
-
- /* get the rendering mode */
- int renderMode = t.getRenderingMode();
-
- Bitmap overlayBitmap = ((OverlayFrame)overlay).getBitmap();
-
- /*
- * Check if the resize of Overlay is needed with rendering mode applied
- * because of change in export dimensions
- */
- int resizedRGBFileHeight = ((OverlayFrame)overlay).getResizedRGBSizeHeight();
- int resizedRGBFileWidth = ((OverlayFrame)overlay).getResizedRGBSizeWidth();
-
- /* Get original bitmap width if it is not resized */
- if(resizedRGBFileWidth == 0) {
- resizedRGBFileWidth = overlayBitmap.getWidth();
- }
- /* Get original bitmap height if it is not resized */
- if(resizedRGBFileHeight == 0) {
- resizedRGBFileHeight = overlayBitmap.getHeight();
- }
-
- if (resizedRGBFileWidth != width || resizedRGBFileHeight != height
- || (!(new File(((OverlayFrame)overlay).getFilename()).exists()))) {
- /*
- * Create the canvas bitmap
- */
- final Bitmap destBitmap = Bitmap.createBitmap((int)width,
- (int)height,
- Bitmap.Config.ARGB_8888);
- final Canvas overlayCanvas = new Canvas(destBitmap);
- final Rect destRect;
- final Rect srcRect;
-
- switch (renderMode) {
- case MediaItem.RENDERING_MODE_STRETCH: {
- destRect = new Rect(0, 0, overlayCanvas.getWidth(),
- overlayCanvas.getHeight());
- srcRect = new Rect(0, 0, overlayBitmap.getWidth(),
- overlayBitmap.getHeight());
- break;
- }
-
- case MediaItem.RENDERING_MODE_BLACK_BORDER: {
- int left, right, top, bottom;
- float aROverlayImage, aRCanvas;
- aROverlayImage = (float)(overlayBitmap.getWidth()) /
- (float)(overlayBitmap.getHeight());
-
- aRCanvas = (float)(overlayCanvas.getWidth()) /
- (float)(overlayCanvas.getHeight());
-
- if (aROverlayImage > aRCanvas) {
- int newHeight = ((overlayCanvas.getWidth() * overlayBitmap.getHeight())
- / overlayBitmap.getWidth());
- left = 0;
- top = (overlayCanvas.getHeight() - newHeight) / 2;
- right = overlayCanvas.getWidth();
- bottom = top + newHeight;
- } else {
- int newWidth = ((overlayCanvas.getHeight() * overlayBitmap.getWidth())
- / overlayBitmap.getHeight());
- left = (overlayCanvas.getWidth() - newWidth) / 2;
- top = 0;
- right = left + newWidth;
- bottom = overlayCanvas.getHeight();
- }
-
- destRect = new Rect(left, top, right, bottom);
- srcRect = new Rect(0, 0, overlayBitmap.getWidth(), overlayBitmap.getHeight());
- break;
- }
-
- case MediaItem.RENDERING_MODE_CROPPING: {
- // Calculate the source rect
- int left, right, top, bottom;
- float aROverlayImage, aRCanvas;
- aROverlayImage = (float)(overlayBitmap.getWidth()) /
- (float)(overlayBitmap.getHeight());
- aRCanvas = (float)(overlayCanvas.getWidth()) /
- (float)(overlayCanvas.getHeight());
- if (aROverlayImage < aRCanvas) {
- int newHeight = ((overlayBitmap.getWidth() * overlayCanvas.getHeight())
- / overlayCanvas.getWidth());
-
- left = 0;
- top = (overlayBitmap.getHeight() - newHeight) / 2;
- right = overlayBitmap.getWidth();
- bottom = top + newHeight;
- } else {
- int newWidth = ((overlayBitmap.getHeight() * overlayCanvas.getWidth())
- / overlayCanvas.getHeight());
- left = (overlayBitmap.getWidth() - newWidth) / 2;
- top = 0;
- right = left + newWidth;
- bottom = overlayBitmap.getHeight();
- }
-
- srcRect = new Rect(left, top, right, bottom);
- destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
- break;
- }
-
- default: {
- throw new IllegalStateException("Rendering mode: " + renderMode);
- }
- }
-
- overlayCanvas.drawBitmap(overlayBitmap, srcRect, destRect, sResizePaint);
- overlayCanvas.setBitmap(null);
-
- /*
- * Write to the dest file
- */
- String outFileName = ((OverlayFrame)overlay).getFilename();
-
- /*
- * Save the image to same rgb file
- */
- if (outFileName != null) {
- new File(outFileName).delete();
- }
-
- final FileOutputStream fl = new FileOutputStream(outFileName);
- final DataOutputStream dos = new DataOutputStream(fl);
-
- /*
- * Populate the rgb file with bitmap data
- */
- final int [] framingBuffer = new int[width];
- ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
- IntBuffer intBuffer;
-
- byte[] array = byteBuffer.array();
- int tmp = 0;
- while(tmp < height) {
- destBitmap.getPixels(framingBuffer,0,width,0,tmp,width,1);
- intBuffer = byteBuffer.asIntBuffer();
- intBuffer.put(framingBuffer,0,width);
- dos.write(array);
- tmp += 1;
- }
- fl.flush();
- fl.close();
-
- /*
- * Set the resized RGB width and height
- */
- ((OverlayFrame)overlay).setResizedRGBSize(width, height);
- }
- }
-}
diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java
deleted file mode 100644
index fa9d26d..0000000
--- a/media/java/android/media/videoeditor/Transition.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.media.videoeditor.MediaArtistNativeHelper.AlphaMagicSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.AudioTransition;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EditSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EffectSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.SlideTransitionSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.TransitionSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.VideoTransition;
-
-/**
- * This class is super class for all transitions. Transitions (with the
- * exception of TransitionAtStart and TransitioAtEnd) can only be inserted
- * between media items.
- *
- * Adding a transition between MediaItems makes the
- * duration of the storyboard shorter by the duration of the Transition itself.
- * As a result, if the duration of the transition is larger than the smaller
- * duration of the two MediaItems associated with the Transition, an exception
- * will be thrown.
- *
- * During a transition, the audio track are cross-fading
- * automatically. {@hide}
- */
-public abstract class Transition {
- /**
- * The transition behavior
- */
- private static final int BEHAVIOR_MIN_VALUE = 0;
-
- /** The transition starts slowly and speed up */
- public static final int BEHAVIOR_SPEED_UP = 0;
- /** The transition start fast and speed down */
- public static final int BEHAVIOR_SPEED_DOWN = 1;
- /** The transition speed is constant */
- public static final int BEHAVIOR_LINEAR = 2;
- /** The transition starts fast and ends fast with a slow middle */
- public static final int BEHAVIOR_MIDDLE_SLOW = 3;
- /** The transition starts slowly and ends slowly with a fast middle */
- public static final int BEHAVIOR_MIDDLE_FAST = 4;
-
- private static final int BEHAVIOR_MAX_VALUE = 4;
-
- /**
- * The unique id of the transition
- */
- private final String mUniqueId;
-
- /**
- * The transition is applied at the end of this media item
- */
- private final MediaItem mAfterMediaItem;
- /**
- * The transition is applied at the beginning of this media item
- */
- private final MediaItem mBeforeMediaItem;
-
- /**
- * The transition behavior
- */
- protected final int mBehavior;
-
- /**
- * The transition duration
- */
- protected long mDurationMs;
-
- /**
- * The transition filename
- */
- protected String mFilename;
-
- protected MediaArtistNativeHelper mNativeHelper;
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private Transition() {
- this(null, null, null, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this
- * media item
- * @param beforeMediaItem The transition is applied to the beginning of
- * this media item
- * @param durationMs The duration of the transition in milliseconds
- * @param behavior The transition behavior
- */
- protected Transition(String transitionId, MediaItem afterMediaItem,
- MediaItem beforeMediaItem,long durationMs,
- int behavior) {
- if (behavior < BEHAVIOR_MIN_VALUE || behavior > BEHAVIOR_MAX_VALUE) {
- throw new IllegalArgumentException("Invalid behavior: " + behavior);
- }
- if ((afterMediaItem == null) && (beforeMediaItem == null)) {
- throw new IllegalArgumentException("Null media items");
- }
- mUniqueId = transitionId;
- mAfterMediaItem = afterMediaItem;
- mBeforeMediaItem = beforeMediaItem;
- mDurationMs = durationMs;
- mBehavior = behavior;
- mNativeHelper = null;
- if (durationMs > getMaximumDuration()) {
- throw new IllegalArgumentException("The duration is too large");
- }
- if (afterMediaItem != null) {
- mNativeHelper = afterMediaItem.getNativeContext();
- }else {
- mNativeHelper = beforeMediaItem.getNativeContext();
- }
- }
-
- /**
- * Get the ID of the transition.
- *
- * @return The ID of the transition
- */
- public String getId() {
- return mUniqueId;
- }
-
- /**
- * Get the media item at the end of which the transition is applied.
- *
- * @return The media item at the end of which the transition is applied
- */
- public MediaItem getAfterMediaItem() {
- return mAfterMediaItem;
- }
-
- /**
- * Get the media item at the beginning of which the transition is applied.
- *
- * @return The media item at the beginning of which the transition is
- * applied
- */
- public MediaItem getBeforeMediaItem() {
- return mBeforeMediaItem;
- }
-
- /**
- * Set the duration of the transition.
- *
- * @param durationMs the duration of the transition in milliseconds
- */
- public void setDuration(long durationMs) {
- if (durationMs > getMaximumDuration()) {
- throw new IllegalArgumentException("The duration is too large");
- }
-
- mDurationMs = durationMs;
- invalidate();
- mNativeHelper.setGeneratePreview(true);
- }
-
- /**
- * Get the duration of the transition.
- *
- * @return the duration of the transition in milliseconds
- */
- public long getDuration() {
- return mDurationMs;
- }
-
- /**
- * The duration of a transition cannot be greater than half of the minimum
- * duration of the bounding media items.
- *
- * @return The maximum duration of this transition
- */
- public long getMaximumDuration() {
- if (mAfterMediaItem == null) {
- return mBeforeMediaItem.getTimelineDuration() / 2;
- } else if (mBeforeMediaItem == null) {
- return mAfterMediaItem.getTimelineDuration() / 2;
- } else {
- return (Math.min(mAfterMediaItem.getTimelineDuration(),
- mBeforeMediaItem.getTimelineDuration()) / 2);
- }
- }
-
- /**
- * Get the behavior of the transition.
- *
- * @return The behavior
- */
- public int getBehavior() {
- return mBehavior;
- }
-
- /**
- * Get the transition data.
- *
- * @return The transition data in TransitionSettings object
- * {@link android.media.videoeditor.MediaArtistNativeHelper.TransitionSettings}
- */
- TransitionSettings getTransitionSettings() {
- TransitionAlpha transitionAlpha = null;
- TransitionSliding transitionSliding = null;
- TransitionCrossfade transitionCrossfade = null;
- TransitionFadeBlack transitionFadeBlack = null;
- TransitionSettings transitionSetting = null;
- transitionSetting = new TransitionSettings();
- transitionSetting.duration = (int)getDuration();
- if (this instanceof TransitionAlpha) {
- transitionAlpha = (TransitionAlpha)this;
- transitionSetting.videoTransitionType = VideoTransition.ALPHA_MAGIC;
- transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
- transitionSetting.transitionBehaviour = mNativeHelper
- .getVideoTransitionBehaviour(transitionAlpha.getBehavior());
- transitionSetting.alphaSettings = new AlphaMagicSettings();
- transitionSetting.slideSettings = null;
- transitionSetting.alphaSettings.file = transitionAlpha.getPNGMaskFilename();
- transitionSetting.alphaSettings.blendingPercent = transitionAlpha.getBlendingPercent();
- transitionSetting.alphaSettings.invertRotation = transitionAlpha.isInvert();
- transitionSetting.alphaSettings.rgbWidth = transitionAlpha.getRGBFileWidth();
- transitionSetting.alphaSettings.rgbHeight = transitionAlpha.getRGBFileHeight();
-
- } else if (this instanceof TransitionSliding) {
- transitionSliding = (TransitionSliding)this;
- transitionSetting.videoTransitionType = VideoTransition.SLIDE_TRANSITION;
- transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
- transitionSetting.transitionBehaviour = mNativeHelper
- .getVideoTransitionBehaviour(transitionSliding.getBehavior());
- transitionSetting.alphaSettings = null;
- transitionSetting.slideSettings = new SlideTransitionSettings();
- transitionSetting.slideSettings.direction = mNativeHelper
- .getSlideSettingsDirection(transitionSliding.getDirection());
- } else if (this instanceof TransitionCrossfade) {
- transitionCrossfade = (TransitionCrossfade)this;
- transitionSetting.videoTransitionType = VideoTransition.CROSS_FADE;
- transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
- transitionSetting.transitionBehaviour = mNativeHelper
- .getVideoTransitionBehaviour(transitionCrossfade.getBehavior());
- transitionSetting.alphaSettings = null;
- transitionSetting.slideSettings = null;
- } else if (this instanceof TransitionFadeBlack) {
- transitionFadeBlack = (TransitionFadeBlack)this;
- transitionSetting.videoTransitionType = VideoTransition.FADE_BLACK;
- transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
- transitionSetting.transitionBehaviour = mNativeHelper
- .getVideoTransitionBehaviour(transitionFadeBlack.getBehavior());
- transitionSetting.alphaSettings = null;
- transitionSetting.slideSettings = null;
- }
-
- return transitionSetting;
- }
-
- /**
- * Checks if the effect and overlay applied on a media item
- * overlaps with the transition on media item.
- *
- * @param m The media item
- * @param clipSettings The ClipSettings object
- * @param clipNo The clip no.(out of the two media items
- * associated with current transition)for which the effect
- * clip should be generated
- * @return List of effects that overlap with the transition
- */
-
- List<EffectSettings> isEffectandOverlayOverlapping(MediaItem m, ClipSettings clipSettings,
- int clipNo) {
- List<Effect> effects;
- List<Overlay> overlays;
- List<EffectSettings> effectSettings = new ArrayList<EffectSettings>();
- EffectSettings tmpEffectSettings;
-
- overlays = m.getAllOverlays();
- for (Overlay overlay : overlays) {
- tmpEffectSettings = mNativeHelper.getOverlaySettings((OverlayFrame)overlay);
- mNativeHelper.adjustEffectsStartTimeAndDuration(tmpEffectSettings,
- clipSettings.beginCutTime, clipSettings.endCutTime);
- if (tmpEffectSettings.duration != 0) {
- effectSettings.add(tmpEffectSettings);
- }
- }
-
- effects = m.getAllEffects();
- for (Effect effect : effects) {
- if (effect instanceof EffectColor) {
- tmpEffectSettings = mNativeHelper.getEffectSettings((EffectColor)effect);
- mNativeHelper.adjustEffectsStartTimeAndDuration(tmpEffectSettings,
- clipSettings.beginCutTime, clipSettings.endCutTime);
- if (tmpEffectSettings.duration != 0) {
- if (m instanceof MediaVideoItem) {
- tmpEffectSettings.fiftiesFrameRate = mNativeHelper
- .GetClosestVideoFrameRate(((MediaVideoItem)m).getFps());
- }
- effectSettings.add(tmpEffectSettings);
- }
- }
- }
-
- return effectSettings;
- }
-
- /**
- * Generate the video clip for the specified transition. This method may
- * block for a significant amount of time. Before the method completes
- * execution it sets the mFilename to the name of the newly generated
- * transition video clip file.
- */
- void generate() {
- MediaItem m1 = this.getAfterMediaItem();
- MediaItem m2 = this.getBeforeMediaItem();
- ClipSettings clipSettings1 = new ClipSettings();
- ClipSettings clipSettings2 = new ClipSettings();
- TransitionSettings transitionSetting = null;
- EditSettings editSettings = new EditSettings();
- List<EffectSettings> effectSettings_clip1;
- List<EffectSettings> effectSettings_clip2;
-
- String output = null;
-
- if (mNativeHelper == null) {
- if (m1 != null)
- mNativeHelper = m1.getNativeContext();
- else if (m2 != null)
- mNativeHelper = m2.getNativeContext();
- }
- transitionSetting = getTransitionSettings();
- if (m1 != null && m2 != null) {
- /* transition between media items */
- clipSettings1 = m1.getClipSettings();
- clipSettings2 = m2.getClipSettings();
- clipSettings1.beginCutTime = (int)(clipSettings1.endCutTime -
- this.mDurationMs);
- clipSettings2.endCutTime = (int)(clipSettings2.beginCutTime +
- this.mDurationMs);
- /*
- * Check how many effects and overlays overlap with transition and
- * generate effect clip first if there is any overlap
- */
- effectSettings_clip1 = isEffectandOverlayOverlapping(m1, clipSettings1,1);
- effectSettings_clip2 = isEffectandOverlayOverlapping(m2, clipSettings2,2);
- for (int index = 0; index < effectSettings_clip2.size(); index++ ) {
- effectSettings_clip2.get(index).startTime += this.mDurationMs;
- }
- editSettings.effectSettingsArray =
- new EffectSettings[effectSettings_clip1.size()
- + effectSettings_clip2.size()];
- int i=0,j=0;
- while (i < effectSettings_clip1.size()) {
- editSettings.effectSettingsArray[j] = effectSettings_clip1.get(i);
- i++;
- j++;
- }
- i=0;
- while (i < effectSettings_clip2.size()) {
- editSettings.effectSettingsArray[j] = effectSettings_clip2.get(i);
- i++;
- j++;
- }
- } else if (m1 == null && m2 != null) {
- /* begin transition at first media item */
- m2.generateBlankFrame(clipSettings1);
- clipSettings2 = m2.getClipSettings();
- clipSettings1.endCutTime = (int)(this.mDurationMs + 50);
- clipSettings2.endCutTime = (int)(clipSettings2.beginCutTime +
- this.mDurationMs);
- /*
- * Check how many effects and overlays overlap with transition and
- * generate effect clip first if there is any overlap
- */
- effectSettings_clip2 = isEffectandOverlayOverlapping(m2, clipSettings2,2);
- for (int index = 0; index < effectSettings_clip2.size(); index++ ) {
- effectSettings_clip2.get(index).startTime += this.mDurationMs;
- }
- editSettings.effectSettingsArray = new EffectSettings[effectSettings_clip2.size()];
- int i=0, j=0;
- while (i < effectSettings_clip2.size()) {
- editSettings.effectSettingsArray[j] = effectSettings_clip2.get(i);
- i++;
- j++;
- }
- } else if (m1 != null && m2 == null) {
- /* end transition at last media item */
- clipSettings1 = m1.getClipSettings();
- m1.generateBlankFrame(clipSettings2);
- clipSettings1.beginCutTime = (int)(clipSettings1.endCutTime -
- this.mDurationMs);
- clipSettings2.endCutTime = (int)(this.mDurationMs + 50);
- /*
- * Check how many effects and overlays overlap with transition and
- * generate effect clip first if there is any overlap
- */
- effectSettings_clip1 = isEffectandOverlayOverlapping(m1, clipSettings1,1);
- editSettings.effectSettingsArray = new EffectSettings[effectSettings_clip1.size()];
- int i=0,j=0;
- while (i < effectSettings_clip1.size()) {
- editSettings.effectSettingsArray[j] = effectSettings_clip1.get(i);
- i++;
- j++;
- }
- }
-
- editSettings.clipSettingsArray = new ClipSettings[2];
- editSettings.clipSettingsArray[0] = clipSettings1;
- editSettings.clipSettingsArray[1] = clipSettings2;
- editSettings.backgroundMusicSettings = null;
- editSettings.transitionSettingsArray = new TransitionSettings[1];
- editSettings.transitionSettingsArray[0] = transitionSetting;
- output = mNativeHelper.generateTransitionClip(editSettings, mUniqueId,
- m1, m2,this);
- setFilename(output);
- }
-
-
- /**
- * Set the transition filename.
- */
- void setFilename(String filename) {
- mFilename = filename;
- }
-
- /**
- * Get the transition filename.
- */
- String getFilename() {
- return mFilename;
- }
-
- /**
- * Remove any resources associated with this transition
- */
- void invalidate() {
- if (mFilename != null) {
- new File(mFilename).delete();
- mFilename = null;
- }
- }
-
- /**
- * Check if the transition is generated.
- *
- * @return true if the transition is generated
- */
- boolean isGenerated() {
- return (mFilename != null);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public boolean equals(Object object) {
- if (!(object instanceof Transition)) {
- return false;
- }
- return mUniqueId.equals(((Transition)object).mUniqueId);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public int hashCode() {
- return mUniqueId.hashCode();
- }
-}
diff --git a/media/java/android/media/videoeditor/TransitionAlpha.java b/media/java/android/media/videoeditor/TransitionAlpha.java
deleted file mode 100644
index 22788d4..0000000
--- a/media/java/android/media/videoeditor/TransitionAlpha.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-/**
- * This class allows to render an "alpha blending" transition according to a
- * bitmap mask. The mask shows the shape of the transition all along the
- * duration of the transition: just before the transition, video 1 is fully
- * displayed. When the transition starts, as the time goes on, pixels of video 2
- * replace pixels of video 1 according to the gray scale pixel value of the
- * mask.
- * {@hide}
- */
-public class TransitionAlpha extends Transition {
- /** This is the input JPEG file for the mask */
- private final String mMaskFilename;
-
- /**
- * This is percentage (between 0 and 100) of blending between video 1 and
- * video 2 if this value equals 0, then the mask is strictly applied if this
- * value equals 100, then the mask is not at all applied (no transition
- * effect)
- */
- private final int mBlendingPercent;
-
- /**
- * If true, this value inverts the direction of the mask: white pixels of
- * the mask show video 2 pixels first black pixels of the mask show video 2
- * pixels last.
- */
- private final boolean mIsInvert;
-
-
- private int mWidth;
- private int mHeight;
- private String mRGBMaskFile;
-
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private TransitionAlpha() {
- this(null, null, null, 0, 0, null, 0, false);
- }
-
- /**
- * Constructor
- *
- * @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this media
- * item
- * @param beforeMediaItem The transition is applied to the beginning of this
- * media item
- * @param durationMs duration of the transition in milliseconds
- * @param behavior behavior is one of the behavior defined in Transition
- * class
- * @param maskFilename JPEG file name. The dimension of the image
- * corresponds to 720p (16:9 aspect ratio). Mask files are
- * shared between video editors and can be created in the
- * projects folder (the parent folder for all projects).
- * @param blendingPercent The blending percent applied
- * @param invert true to invert the direction of the alpha blending
- * @throws IllegalArgumentException if behavior is not supported, or if
- * direction are not supported.
- */
- public TransitionAlpha(String transitionId, MediaItem afterMediaItem,
- MediaItem beforeMediaItem, long durationMs, int behavior,
- String maskFilename, int blendingPercent, boolean invert) {
- super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
-
- /**
- * Generate a RGB file for the supplied mask file
- */
- final BitmapFactory.Options dbo = new BitmapFactory.Options();
- dbo.inJustDecodeBounds = true;
- if (!new File(maskFilename).exists())
- throw new IllegalArgumentException("File not Found " + maskFilename);
- BitmapFactory.decodeFile(maskFilename, dbo);
-
- mWidth = dbo.outWidth;
- mHeight = dbo.outHeight;
-
- mRGBMaskFile = String.format(mNativeHelper.getProjectPath() +
- "/" + "mask" + transitionId+ ".rgb");
-
-
- FileOutputStream fl = null;
-
- try{
- fl = new FileOutputStream(mRGBMaskFile);
- } catch (IOException e) {
- /* catch IO exception */
- }
- final DataOutputStream dos = new DataOutputStream(fl);
-
- if (fl != null) {
- /**
- * Write to rgb file
- */
- Bitmap imageBitmap = BitmapFactory.decodeFile(maskFilename);
- final int [] framingBuffer = new int[mWidth];
- ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
- IntBuffer intBuffer;
-
- byte[] array = byteBuffer.array();
- int tmp = 0;
- while (tmp < mHeight) {
- imageBitmap.getPixels(framingBuffer, 0, mWidth, 0, tmp,mWidth, 1);
- intBuffer = byteBuffer.asIntBuffer();
- intBuffer.put(framingBuffer,0,mWidth);
- try {
- dos.write(array);
- } catch (IOException e) {
- /* catch file write error */
- }
- tmp += 1;
- }
-
- imageBitmap.recycle();
- try{
- fl.close();
- }catch (IOException e) {
- /* file close error */
- }
- }
-
- /**
- * Capture the details
- */
- mMaskFilename = maskFilename;
- mBlendingPercent = blendingPercent;
- mIsInvert = invert;
- }
-
- public int getRGBFileWidth() {
- return mWidth;
- }
-
- public int getRGBFileHeight() {
- return mHeight;
- }
-
- public String getPNGMaskFilename() {
- return mRGBMaskFile;
- }
-
- /**
- * Get the blending percentage
- *
- * @return The blending percentage
- */
- public int getBlendingPercent() {
- return mBlendingPercent;
- }
-
- /**
- * Get the filename of the mask.
- *
- * @return The mask filename
- */
- public String getMaskFilename() {
- return mMaskFilename;
- }
-
- /**
- * Check if the alpha blending direction is inverted.
- *
- * @return true if the direction of the alpha blending is inverted
- */
- public boolean isInvert() {
- return mIsInvert;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- public void generate() {
- super.generate();
- }
-}
diff --git a/media/java/android/media/videoeditor/TransitionCrossfade.java b/media/java/android/media/videoeditor/TransitionCrossfade.java
deleted file mode 100644
index 417c64e..0000000
--- a/media/java/android/media/videoeditor/TransitionCrossfade.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-
-/**
- * This class allows to render a crossfade (dissolve) effect transition between
- * two videos
- * {@hide}
- */
-public class TransitionCrossfade extends Transition {
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private TransitionCrossfade() {
- this(null, null, null, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this
- * media item
- * @param beforeMediaItem The transition is applied to the beginning of
- * this media item
- * @param durationMs duration of the transition in milliseconds
- * @param behavior behavior is one of the behavior defined in Transition
- * class
- *
- * @throws IllegalArgumentException if behavior is not supported.
- */
- public TransitionCrossfade(String transitionId, MediaItem afterMediaItem,
- MediaItem beforeMediaItem, long durationMs, int behavior) {
- super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void generate() {
- super.generate();
- }
-}
diff --git a/media/java/android/media/videoeditor/TransitionFadeBlack.java b/media/java/android/media/videoeditor/TransitionFadeBlack.java
deleted file mode 100644
index da07cf0..0000000
--- a/media/java/android/media/videoeditor/TransitionFadeBlack.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-
-/**
- * This class is used to render a fade to black and fade from black transition
- * between two media items.
- * {@hide}
- */
-public class TransitionFadeBlack extends Transition {
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private TransitionFadeBlack() {
- this(null, null, null, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this
- * media item
- * @param beforeMediaItem The transition is applied to the beginning of
- * this media item
- * @param durationMs duration of the transition
- * @param behavior behavior is one of the behavior defined in Transition
- * class
- *
- * @throws IllegalArgumentException if behavior is not supported.
- */
- public TransitionFadeBlack(String transitionId, MediaItem afterMediaItem,
- MediaItem beforeMediaItem, long durationMs, int behavior) {
- super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void generate() {
- super.generate();
- }
-}
diff --git a/media/java/android/media/videoeditor/TransitionSliding.java b/media/java/android/media/videoeditor/TransitionSliding.java
deleted file mode 100644
index 57610ab..0000000
--- a/media/java/android/media/videoeditor/TransitionSliding.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-/**
- * This class allows to create sliding transitions
- * {@hide}
- */
-public class TransitionSliding extends Transition {
-
- /** Video 1 is pushed to the right while video 2 is coming from left */
- public final static int DIRECTION_RIGHT_OUT_LEFT_IN = 0;
- /** Video 1 is pushed to the left while video 2 is coming from right */
- public static final int DIRECTION_LEFT_OUT_RIGHT_IN = 1;
- /** Video 1 is pushed to the top while video 2 is coming from bottom */
- public static final int DIRECTION_TOP_OUT_BOTTOM_IN = 2;
- /** Video 1 is pushed to the bottom while video 2 is coming from top */
- public static final int DIRECTION_BOTTOM_OUT_TOP_IN = 3;
-
- // The sliding transitions
- private final int mSlidingDirection;
-
- /**
- * An object of this type cannot be instantiated by using the default
- * constructor
- */
- @SuppressWarnings("unused")
- private TransitionSliding() {
- this(null, null, null, 0, 0, 0);
- }
-
- /**
- * Constructor
- *
- * @param transitionId The transition id
- * @param afterMediaItem The transition is applied to the end of this
- * media item
- * @param beforeMediaItem The transition is applied to the beginning of
- * this media item
- * @param durationMs duration of the transition in milliseconds
- * @param behavior behavior is one of the behavior defined in Transition
- * class
- * @param direction direction shall be one of the supported directions like
- * RIGHT_OUT_LEFT_IN
- *
- * @throws IllegalArgumentException if behavior is not supported.
- */
- public TransitionSliding(String transitionId, MediaItem afterMediaItem,
- MediaItem beforeMediaItem, long durationMs, int behavior,
- int direction) {
- super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
- switch (direction) {
- case DIRECTION_RIGHT_OUT_LEFT_IN:
- case DIRECTION_LEFT_OUT_RIGHT_IN:
- case DIRECTION_TOP_OUT_BOTTOM_IN:
- case DIRECTION_BOTTOM_OUT_TOP_IN:
- break;
-
- default:
- throw new IllegalArgumentException("Invalid direction");
- }
- mSlidingDirection = direction;
- }
-
- /**
- * Get the sliding direction.
- *
- * @return The sliding direction
- */
- public int getDirection() {
- return mSlidingDirection;
- }
-
- /*
- * {@inheritDoc}
- */
- @Override
- void generate() {
- super.generate();
- }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
deleted file mode 100644
index 08d27d4..0000000
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.CancellationException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.view.SurfaceHolder;
-
-/**
- * This is the interface implemented by classes which provide video editing
- * functionality. The VideoEditor implementation class manages all input and
- * output files. Unless specifically mentioned, methods are blocking. A typical
- * editing session may consist of the following sequence of operations:
- *
- * <ul>
- * <li>Add a set of MediaItems</li>
- * <li>Apply a set of Transitions between MediaItems</li>
- * <li>Add Effects and Overlays to media items</li>
- * <li>Preview the movie at any time</li>
- * <li>Save the VideoEditor implementation class internal state</li>
- * <li>Release the VideoEditor implementation class instance by invoking
- * {@link #release()}
- * </ul>
- * The internal VideoEditor state consists of the following elements:
- * <ul>
- * <li>Ordered & trimmed MediaItems</li>
- * <li>Transition video clips</li>
- * <li>Overlays</li>
- * <li>Effects</li>
- * <li>Audio waveform for the background audio and MediaItems</li>
- * <li>Project thumbnail</li>
- * <li>Last exported movie.</li>
- * <li>Other project specific data such as the current aspect ratio.</li>
- * </ul>
- * {@hide}
- */
-public interface VideoEditor {
- /**
- * The file name of the project thumbnail
- */
- public static final String THUMBNAIL_FILENAME = "thumbnail.jpg";
-
- /**
- * Use this value instead of the specific end of the storyboard timeline
- * value.
- */
- public final static int DURATION_OF_STORYBOARD = -1;
-
- /**
- * Maximum supported file size
- */
- public static final long MAX_SUPPORTED_FILE_SIZE = 2147483648L;
-
- /**
- * This listener interface is used by the VideoEditor to emit preview
- * progress notifications. This callback should be invoked after the number
- * of frames specified by
- * {@link #startPreview(SurfaceHolder surfaceHolder, long fromMs,
- * int callbackAfterFrameCount, PreviewProgressListener listener)}
- */
- public interface PreviewProgressListener {
- /**
- * This method notifies the listener of the current time position while
- * previewing a project.
- *
- * @param videoEditor The VideoEditor instance
- * @param timeMs The current preview position (expressed in milliseconds
- * since the beginning of the storyboard timeline).
- * @param overlayData The overlay data (null if the overlay data
- * is unchanged)
- */
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData);
- /**
- * This method notifies the listener when the preview is started
- * previewing a project.
- *
- * @param videoEditor The VideoEditor instance
- */
- public void onStart(VideoEditor videoEditor);
-
- /**
- * This method notifies the listener when the preview is stopped
- * previewing a project.
- *
- * @param videoEditor The VideoEditor instance
- */
- public void onStop(VideoEditor videoEditor);
-
- /**
- * This method notifies the listener when error has occurred during
- * previewing a project.
- *
- * @param videoEditor The VideoEditor instance
- * @param error The error that has occurred
- * FIXME: We should pass well-defined error code to the application;
- * but for now, we just pass whatever error code reported by the native layer.
- */
- public void onError(VideoEditor videoEditor, int error);
- }
-
- /**
- * This listener interface is used by the VideoEditor to emit export status
- * notifications.
- * {@link #export(String filename, ExportProgressListener listener,
- * int height, int bitrate)}
- */
- public interface ExportProgressListener {
- /**
- * This method notifies the listener of the progress status of a export
- * operation.
- *
- * @param videoEditor The VideoEditor instance
- * @param filename The name of the file which is in the process of being
- * exported.
- * @param progress The progress in %. At the beginning of the export,
- * this value is set to 0; at the end, the value is set to 100.
- */
- public void onProgress(VideoEditor videoEditor, String filename,
- int progress);
- }
-
- public interface MediaProcessingProgressListener {
- /**
- * Values used for the action parameter
- */
- public static final int ACTION_ENCODE = 1;
- public static final int ACTION_DECODE = 2;
-
- /**
- * This method notifies the listener of the progress status of
- * processing a media object such as a Transition, AudioTrack & Kenburns
- * This method may be called maximum 100 times for one operation.
- *
- * @param object The object that is being processed such as a Transition
- * or AudioTrack
- * @param action The type of processing being performed
- * @param progress The progress in %. At the beginning of the operation,
- * this value is set to 0; at the end, the value is set to 100.
- */
- public void onProgress(Object item, int action, int progress);
- }
-
- /**
- * The overlay data
- */
- public static final class OverlayData {
- // Instance variables
- private Bitmap mOverlayBitmap;
- private int mRenderingMode;
- private boolean mClear;
- private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
- /**
- * Default constructor
- */
- public OverlayData() {
- mOverlayBitmap = null;
- mRenderingMode = MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS;
- mClear = false;
- }
-
- /**
- * Releases the bitmap
- */
- public void release() {
- if (mOverlayBitmap != null) {
- mOverlayBitmap.recycle();
- mOverlayBitmap = null;
- }
- }
-
- /**
- * Check if the overlay needs to be rendered
- *
- * @return true if rendering is needed
- */
- public boolean needsRendering() {
- return (mClear || mOverlayBitmap != null);
- }
-
- /**
- * Store the overlay data
- *
- * @param overlayBitmap The overlay bitmap
- * @param renderingMode The rendering mode
- */
- void set(Bitmap overlayBitmap, int renderingMode) {
- mOverlayBitmap = overlayBitmap;
- mRenderingMode = renderingMode;
- mClear = false;
- }
-
- /**
- * Clear the overlay
- */
- void setClear() {
- mClear = true;
- }
-
- /**
- * Render the overlay by either clearing it or by
- * rendering the overlay bitmap with the specified
- * rendering mode
- *
- * @param destBitmap The destination bitmap
- */
- public void renderOverlay(Bitmap destBitmap) {
- if (mClear) {
- destBitmap.eraseColor(Color.TRANSPARENT);
- } else if (mOverlayBitmap != null) {
- final Canvas overlayCanvas = new Canvas(destBitmap);
- final Rect destRect;
- final Rect srcRect;
- switch (mRenderingMode) {
- case MediaArtistNativeHelper.MediaRendering.RESIZING: {
- destRect = new Rect(0, 0, overlayCanvas.getWidth(),
- overlayCanvas.getHeight());
- srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(),
- mOverlayBitmap.getHeight());
- break;
- }
-
- case MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS: {
- int left, right, top, bottom;
- float aROverlayImage, aRCanvas;
- aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
- (float)(mOverlayBitmap.getHeight());
-
- aRCanvas = (float)(overlayCanvas.getWidth()) /
- (float)(overlayCanvas.getHeight());
-
- if (aROverlayImage > aRCanvas) {
- int newHeight = ((overlayCanvas.getWidth() * mOverlayBitmap.getHeight())
- / mOverlayBitmap.getWidth());
- left = 0;
- top = (overlayCanvas.getHeight() - newHeight) / 2;
- right = overlayCanvas.getWidth();
- bottom = top + newHeight;
- } else {
- int newWidth = ((overlayCanvas.getHeight() * mOverlayBitmap.getWidth())
- / mOverlayBitmap.getHeight());
- left = (overlayCanvas.getWidth() - newWidth) / 2;
- top = 0;
- right = left + newWidth;
- bottom = overlayCanvas.getHeight();
- }
-
- destRect = new Rect(left, top, right, bottom);
- srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight());
- break;
- }
-
- case MediaArtistNativeHelper.MediaRendering.CROPPING: {
- // Calculate the source rect
- int left, right, top, bottom;
- float aROverlayImage, aRCanvas;
- aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
- (float)(mOverlayBitmap.getHeight());
- aRCanvas = (float)(overlayCanvas.getWidth()) /
- (float)(overlayCanvas.getHeight());
- if (aROverlayImage < aRCanvas) {
- int newHeight = ((mOverlayBitmap.getWidth() * overlayCanvas.getHeight())
- / overlayCanvas.getWidth());
-
- left = 0;
- top = (mOverlayBitmap.getHeight() - newHeight) / 2;
- right = mOverlayBitmap.getWidth();
- bottom = top + newHeight;
- } else {
- int newWidth = ((mOverlayBitmap.getHeight() * overlayCanvas.getWidth())
- / overlayCanvas.getHeight());
- left = (mOverlayBitmap.getWidth() - newWidth) / 2;
- top = 0;
- right = left + newWidth;
- bottom = mOverlayBitmap.getHeight();
- }
-
- srcRect = new Rect(left, top, right, bottom);
- destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
- break;
- }
-
- default: {
- throw new IllegalStateException("Rendering mode: " + mRenderingMode);
- }
- }
-
- destBitmap.eraseColor(Color.TRANSPARENT);
- overlayCanvas.drawBitmap(mOverlayBitmap, srcRect, destRect, sResizePaint);
-
- mOverlayBitmap.recycle();
- }
- }
- }
-
- /**
- * @return The path where the VideoEditor stores all files related to the
- * project
- */
- public String getPath();
-
- /**
- * This method releases all in-memory resources used by the VideoEditor
- * instance. All pending operations such as preview, export and extract
- * audio waveform must be canceled.
- */
- public void release();
-
- /**
- * Persist the current internal state of VideoEditor to the project path.
- * The VideoEditor state may be restored by invoking the
- * {@link VideoEditorFactory#load(String)} method. This method does not
- * release the internal in-memory state of the VideoEditor. To release
- * the in-memory state of the VideoEditor the {@link #release()} method
- * must be invoked.
- *
- * Pending transition generations must be allowed to complete before the
- * state is saved.
- * Pending audio waveform generations must be allowed to complete.
- * Pending export operations must be allowed to continue.
- *
- * @throws IOException if the internal state cannot be saved to project file
- */
- public void save() throws IOException;
-
- /**
- * Create the output movie based on all media items added and the applied
- * storyboard items. This method can take a long time to execute and is
- * blocking. The application will receive progress notifications via the
- * ExportProgressListener. Specific implementations may not support multiple
- * simultaneous export operations. Note that invoking methods which would
- * change the contents of the output movie throw an IllegalStateException
- * while an export operation is pending.
- *
- * The audio and video codecs are automatically selected by the underlying
- * implementation.
- *
- * @param filename The output file name (including the full path)
- * @param height The height of the output video file. The supported values
- * for height are described in the MediaProperties class, for
- * example: HEIGHT_480. The width will be automatically computed
- * according to the aspect ratio provided by
- * {@link #setAspectRatio(int)}
- * @param bitrate The bitrate of the output video file. This is approximate
- * value for the output movie. Supported bitrate values are
- * described in the MediaProperties class for example: BITRATE_384K
- * @param listener The listener for progress notifications. Use null if
- * export progress notifications are not needed.
- *
- * @throws IllegalArgumentException if height or bitrate are not supported
- * or if the audio or video codecs are not supported
- * @throws IOException if output file cannot be created
- * @throws IllegalStateException if a preview or an export is in progress or
- * if no MediaItem has been added
- * @throws CancellationException if export is canceled by calling
- * {@link #cancelExport()}
- * @throws UnsupportOperationException if multiple simultaneous export() are
- * not allowed
- */
- public void export(String filename, int height, int bitrate,
- ExportProgressListener listener)
- throws IOException;
-
- /**
- * Create the output movie based on all media items added and the applied
- * storyboard items. This method can take a long time to execute and is
- * blocking. The application will receive progress notifications via the
- * ExportProgressListener. Specific implementations may not support multiple
- * simultaneous export operations. Note that invoking methods which would
- * change the contents of the output movie throw an IllegalStateException
- * while an export operation is pending.
- *
- * @param filename The output file name (including the full path)
- * @param height The height of the output video file. The supported values
- * for height are described in the MediaProperties class, for
- * example: HEIGHT_480. The width will be automatically computed
- * according to the aspect ratio provided by
- * {@link #setAspectRatio(int)}
- * @param bitrate The bitrate of the output video file. This is approximate
- * value for the output movie. Supported bitrate values are
- * described in the MediaProperties class for example: BITRATE_384K
- * @param audioCodec The audio codec to be used for the export. The audio
- * codec values are defined in the MediaProperties class (e.g.
- * ACODEC_AAC_LC). Note that not all audio codec types are
- * supported for export purposes.
- * @param videoCodec The video codec to be used for the export. The video
- * codec values are defined in the MediaProperties class (e.g.
- * VCODEC_H264). Note that not all video codec types are
- * supported for export purposes.
- * @param listener The listener for progress notifications. Use null if
- * export progress notifications are not needed.
- *
- * @throws IllegalArgumentException if height or bitrate are not supported
- * or if the audio or video codecs are not supported
- * @throws IOException if output file cannot be created
- * @throws IllegalStateException if a preview or an export is in progress or
- * if no MediaItem has been added
- * @throws CancellationException if export is cancelled by calling
- * {@link #cancelExport()}
- * @throws UnsupportOperationException if multiple simultaneous export() are
- * not allowed
- */
- public void export(String filename, int height, int bitrate, int audioCodec,
- int videoCodec, ExportProgressListener listener)
- throws IOException;
-
- /**
- * Cancel the running export operation. This method blocks until the export
- * is cancelled and the exported file (if any) is deleted. If the export
- * completed by the time this method is invoked, the export file will be
- * deleted.
- *
- * @param filename The filename which identifies the export operation to be
- * canceled.
- **/
- public void cancelExport(String filename);
-
- /**
- * Add a media item at the end of the storyboard.
- *
- * @param mediaItem The media item object to add
- *
- * @throws IllegalStateException if a preview or an export is in progress or
- * if the media item id is not unique across all the media items
- * added.
- */
- public void addMediaItem(MediaItem mediaItem);
-
- /**
- * Insert a media item after the media item with the specified id.
- *
- * @param mediaItem The media item object to insert
- * @param afterMediaItemId Insert the mediaItem after the media item
- * identified by this id. If this parameter is null, the media
- * item is inserted at the beginning of the timeline.
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if media item with the specified id does
- * not exist (null is a valid value) or if the media item id is
- * not unique across all the media items added.
- */
- public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId);
-
- /**
- * Move a media item after the media item with the specified id.
- *
- * Note: The project thumbnail is regenerated if the media item is or
- * becomes the first media item in the storyboard timeline.
- *
- * @param mediaItemId The id of the media item to move
- * @param afterMediaItemId Move the media item identified by mediaItemId
- * after the media item identified by this parameter. If this
- * parameter is null, the media item is moved at the beginning of
- * the timeline.
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if one of media item ids is invalid
- * (null is a valid value)
- */
- public void moveMediaItem(String mediaItemId, String afterMediaItemId);
-
- /**
- * Remove the media item with the specified id. If there are transitions
- * before or after this media item, then this/these transition(s) are
- * removed from the storyboard. If the extraction of the audio waveform is
- * in progress, the extraction is canceled and the file is deleted.
- *
- * Effects and overlays associated with the media item will also be removed.
- *
- * Note: The project thumbnail is regenerated if the media item which is
- * removed is the first media item in the storyboard or if the media item is
- * the only one in the storyboard. If the media item is the only one in the
- * storyboard, the project thumbnail will be set to a black frame and the
- * aspect ratio will revert to the default aspect ratio and this method is
- * equivalent to removeAllMediaItems() in this case.
- *
- * @param mediaItemId The unique id of the media item to be removed
- *
- * @return The media item that was removed
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if media item with the specified id does
- * not exist
- */
- public MediaItem removeMediaItem(String mediaItemId);
-
- /**
- * Remove all media items in the storyboard. All effects, overlays and all
- * transitions are also removed.
- *
- * Note: The project thumbnail will be set to a black frame and the aspect
- * ratio will revert to the default aspect ratio.
- *
- * @throws IllegalStateException if a preview or an export is in progress
- */
- public void removeAllMediaItems();
-
- /**
- * Get the list of media items in the order in which it they appear in the
- * storyboard timeline.
- *
- * Note that if any media item source files are no longer
- * accessible, this method will still provide the full list of media items.
- *
- * @return The list of media items. If no media item exist an empty list
- * will be returned.
- */
- public List<MediaItem> getAllMediaItems();
-
- /**
- * Find the media item with the specified id
- *
- * @param mediaItemId The media item id
- *
- * @return The media item with the specified id (null if it does not exist)
- */
- public MediaItem getMediaItem(String mediaItemId);
-
- /**
- * Add a transition between the media items specified by the transition.
- * If a transition existed at the same position it is invalidated and then
- * the transition is replaced. Note that the new transition video clip is
- * not automatically generated by this method. The
- * {@link Transition#generate()} method must be invoked to generate
- * the transition video clip.
- *
- * Note that the TransitionAtEnd and TransitionAtStart are special kinds
- * that can not be applied between two media items.
- *
- * A crossfade audio transition will be automatically applied regardless of
- * the video transition.
- *
- * @param transition The transition to apply
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if the transition duration is larger
- * than the smallest duration of the two media item files or if
- * the two media items specified in the transition are not
- * adjacent
- */
- public void addTransition(Transition transition);
-
- /**
- * Remove the transition with the specified id.
- *
- * @param transitionId The id of the transition to be removed
- *
- * @return The transition that was removed
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if transition with the specified id does
- * not exist
- */
- public Transition removeTransition(String transitionId);
-
- /**
- * Get the list of transitions
- *
- * @return The list of transitions. If no transitions exist an empty list
- * will be returned.
- */
- public List<Transition> getAllTransitions();
-
- /**
- * Find the transition with the specified transition id.
- *
- * @param transitionId The transition id
- *
- * @return The transition
- */
- public Transition getTransition(String transitionId);
-
- /**
- * Add the specified AudioTrack to the storyboard. Note: Specific
- * implementations may support a limited number of audio tracks (e.g. only
- * one audio track)
- *
- * @param audioTrack The AudioTrack to add
- *
- * @throws UnsupportedOperationException if the implementation supports a
- * limited number of audio tracks.
- * @throws IllegalArgumentException if media item is not unique across all
- * the audio tracks already added.
- */
- public void addAudioTrack(AudioTrack audioTrack);
-
- /**
- * Insert an audio track after the audio track with the specified id. Use
- * addAudioTrack to add an audio track at the end of the storyboard
- * timeline.
- *
- * @param audioTrack The audio track object to insert
- * @param afterAudioTrackId Insert the audio track after the audio track
- * identified by this parameter. If this parameter is null the
- * audio track is added at the beginning of the timeline.
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if media item with the specified id does
- * not exist (null is a valid value). if media item is not unique
- * across all the audio tracks already added.
- * @throws UnsupportedOperationException if the implementation supports a
- * limited number of audio tracks
- */
- public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId);
-
- /**
- * Move an AudioTrack after the AudioTrack with the specified id.
- *
- * @param audioTrackId The id of the AudioTrack to move
- * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId
- * after the AudioTrack identified by this parameter. If this
- * parameter is null the audio track is added at the beginning of
- * the timeline.
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if one of media item ids is invalid
- * (null is a valid value)
- */
- public void moveAudioTrack(String audioTrackId, String afterAudioTrackId);
-
- /**
- * Remove the audio track with the specified id. If the extraction of the
- * audio waveform is in progress, the extraction is canceled and the file is
- * deleted.
- *
- * @param audioTrackId The id of the audio track to be removed
- *
- * @return The audio track that was removed
- * @throws IllegalStateException if a preview or an export is in progress
- */
- public AudioTrack removeAudioTrack(String audioTrackId);
-
- /**
- * Get the list of AudioTracks in order in which they appear in the
- * storyboard.
- *
- * Note that if any AudioTrack source files are not accessible anymore,
- * this method will still provide the full list of audio tracks.
- *
- * @return The list of AudioTracks. If no audio tracks exist an empty list
- * will be returned.
- */
- public List<AudioTrack> getAllAudioTracks();
-
- /**
- * Find the AudioTrack with the specified id
- *
- * @param audioTrackId The AudioTrack id
- *
- * @return The AudioTrack with the specified id (null if it does not exist)
- */
- public AudioTrack getAudioTrack(String audioTrackId);
-
- /**
- * Set the aspect ratio used in the preview and the export movie.
- *
- * The default aspect ratio is ASPECTRATIO_16_9 (16:9).
- *
- * @param aspectRatio to apply. If aspectRatio is the same as the current
- * aspect ratio, then this function just returns. The supported
- * aspect ratio are defined in the MediaProperties class for
- * example: ASPECTRATIO_16_9
- *
- * @throws IllegalStateException if a preview or an export is in progress
- * @throws IllegalArgumentException if aspect ratio is not supported
- */
- public void setAspectRatio(int aspectRatio);
-
- /**
- * Get current aspect ratio.
- *
- * @return The aspect ratio as described in MediaProperties
- */
- public int getAspectRatio();
-
- /**
- * Get the preview (and output movie) duration.
- *
- * @return The duration of the preview (and output movie)
- */
- public long getDuration();
-
- /**
- * Render a frame according to the preview aspect ratio and activating all
- * storyboard items relative to the specified time.
- *
- * @param surfaceHolder SurfaceHolder used by the application
- * @param timeMs time corresponding to the frame to display
- * @param overlayData The overlay data
- *
- * @return The accurate time stamp of the frame that is rendered.
- *
- * @throws IllegalStateException if a preview or an export is already in
- * progress
- * @throws IllegalArgumentException if time is negative or beyond the
- * preview duration
- */
- public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
- OverlayData overlayData);
-
- /**
- * This method must be called after any changes made to the storyboard
- * and before startPreview is called. Note that this method may block for an
- * extensive period of time.
- */
- public void generatePreview(MediaProcessingProgressListener listener);
-
- /**
- * Start the preview of all the storyboard items applied on all MediaItems
- * This method does not block (does not wait for the preview to complete).
- * The PreviewProgressListener allows to track the progress at the time
- * interval determined by the callbackAfterFrameCount parameter. The
- * SurfaceHolder has to be created and ready for use before calling this
- * method. The method is a no-op if there are no MediaItems in the
- * storyboard.
- *
- * @param surfaceHolder SurfaceHolder where the preview is rendered.
- * @param fromMs The time (relative to the timeline) at which the preview
- * will start
- * @param toMs The time (relative to the timeline) at which the preview will
- * stop. Use -1 to play to the end of the timeline
- * @param loop true if the preview should be looped once it reaches the end
- * @param callbackAfterFrameCount The listener interface should be invoked
- * after the number of frames specified by this parameter.
- * @param listener The listener which will be notified of the preview
- * progress
- *
- * @throws IllegalArgumentException if fromMs is beyond the preview duration
- * @throws IllegalStateException if a preview or an export is already in
- * progress
- */
- public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs,
- boolean loop,int callbackAfterFrameCount,
- PreviewProgressListener listener);
-
- /**
- * Stop the current preview. This method blocks until ongoing preview is
- * stopped. Ignored if there is no preview running.
- *
- * @return The accurate current time when stop is effective expressed in
- * milliseconds
- */
- public long stopPreview();
-
- /**
- * Clears the preview surface
- *
- * @param surfaceHolder SurfaceHolder where the preview is rendered
- * and needs to be cleared.
- */
- public void clearSurface(SurfaceHolder surfaceHolder);
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorFactory.java b/media/java/android/media/videoeditor/VideoEditorFactory.java
deleted file mode 100644
index 85c329f..0000000
--- a/media/java/android/media/videoeditor/VideoEditorFactory.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-
-/**
- * The VideoEditorFactory class must be used to instantiate VideoEditor objects
- * by creating a new project {@link #create(String)} or by loading an
- * existing project {@link #load(String)}.
- * {@hide}
- */
-public class VideoEditorFactory {
- /**
- * This is the factory method for creating a new VideoEditor instance.
- *
- * @param projectPath The path where all VideoEditor internal
- * files are stored. When a project is deleted the application is
- * responsible for deleting the path and its contents.
- *
- * @return The VideoEditor instance
- *
- * @throws IOException if path does not exist or if the path can
- * not be accessed in read/write mode
- */
- public static VideoEditor create(String projectPath) throws IOException {
- /*
- * If the project path does not exist create it
- */
- final File dir = new File(projectPath);
- if (!dir.exists()) {
- if (!dir.mkdirs()) {
- throw new FileNotFoundException("Cannot create project path: "
- + projectPath);
- } else {
- /*
- * Create the file which hides the media files
- * from the media scanner
- */
- if (!new File(dir, ".nomedia").createNewFile()) {
- throw new FileNotFoundException("Cannot create file .nomedia");
- }
- }
- }
-
- return new VideoEditorImpl(projectPath);
- }
-
- /**
- * This is the factory method for instantiating a VideoEditor from the
- * internal state previously saved with the
- * {@link VideoEditor#save(String)} method.
- *
- * @param projectPath The path where all VideoEditor internal files
- * are stored. When a project is deleted the application is
- * responsible for deleting the path and its contents.
- * @param generatePreview if set to true the
- * {@link MediaEditor#generatePreview(MediaProcessingProgressListener
- * listener)}
- * will be called internally to generate any needed transitions.
- *
- * @return The VideoEditor instance
- *
- * @throws IOException if path does not exist or if the path can
- * not be accessed in read/write mode or if one of the resource
- * media files cannot be retrieved
- */
- public static VideoEditor load(String projectPath, boolean generatePreview)
- throws IOException {
- final VideoEditor videoEditor = new VideoEditorImpl(projectPath);
- if (generatePreview) {
- videoEditor.generatePreview(null);
- }
- return videoEditor;
- }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
deleted file mode 100644
index fbf2eab..0000000
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ /dev/null
@@ -1,1978 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.MediaMetadataRetriever;
-import android.util.Log;
-import android.util.Xml;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.os.Debug;
-import android.os.SystemProperties;
-import android.os.Environment;
-
-import libcore.io.IoUtils;
-
-/**
- * The VideoEditor implementation {@hide}
- */
-public class VideoEditorImpl implements VideoEditor {
- /*
- * Logging
- */
- private static final String TAG = "VideoEditorImpl";
-
- /*
- * The project filename
- */
- private static final String PROJECT_FILENAME = "videoeditor.xml";
-
- /*
- * XML tags
- */
- private static final String TAG_PROJECT = "project";
- private static final String TAG_MEDIA_ITEMS = "media_items";
- private static final String TAG_MEDIA_ITEM = "media_item";
- private static final String TAG_TRANSITIONS = "transitions";
- private static final String TAG_TRANSITION = "transition";
- private static final String TAG_OVERLAYS = "overlays";
- private static final String TAG_OVERLAY = "overlay";
- private static final String TAG_OVERLAY_USER_ATTRIBUTES = "overlay_user_attributes";
- private static final String TAG_EFFECTS = "effects";
- private static final String TAG_EFFECT = "effect";
- private static final String TAG_AUDIO_TRACKS = "audio_tracks";
- private static final String TAG_AUDIO_TRACK = "audio_track";
-
- private static final String ATTR_ID = "id";
- private static final String ATTR_FILENAME = "filename";
- private static final String ATTR_AUDIO_WAVEFORM_FILENAME = "waveform";
- private static final String ATTR_RENDERING_MODE = "rendering_mode";
- private static final String ATTR_ASPECT_RATIO = "aspect_ratio";
- private static final String ATTR_REGENERATE_PCM = "regeneratePCMFlag";
- private static final String ATTR_TYPE = "type";
- private static final String ATTR_DURATION = "duration";
- private static final String ATTR_START_TIME = "start_time";
- private static final String ATTR_BEGIN_TIME = "begin_time";
- private static final String ATTR_END_TIME = "end_time";
- private static final String ATTR_VOLUME = "volume";
- private static final String ATTR_BEHAVIOR = "behavior";
- private static final String ATTR_DIRECTION = "direction";
- private static final String ATTR_BLENDING = "blending";
- private static final String ATTR_INVERT = "invert";
- private static final String ATTR_MASK = "mask";
- private static final String ATTR_BEFORE_MEDIA_ITEM_ID = "before_media_item";
- private static final String ATTR_AFTER_MEDIA_ITEM_ID = "after_media_item";
- private static final String ATTR_COLOR_EFFECT_TYPE = "color_type";
- private static final String ATTR_COLOR_EFFECT_VALUE = "color_value";
- private static final String ATTR_START_RECT_LEFT = "start_l";
- private static final String ATTR_START_RECT_TOP = "start_t";
- private static final String ATTR_START_RECT_RIGHT = "start_r";
- private static final String ATTR_START_RECT_BOTTOM = "start_b";
- private static final String ATTR_END_RECT_LEFT = "end_l";
- private static final String ATTR_END_RECT_TOP = "end_t";
- private static final String ATTR_END_RECT_RIGHT = "end_r";
- private static final String ATTR_END_RECT_BOTTOM = "end_b";
- private static final String ATTR_LOOP = "loop";
- private static final String ATTR_MUTED = "muted";
- private static final String ATTR_DUCK_ENABLED = "ducking_enabled";
- private static final String ATTR_DUCK_THRESHOLD = "ducking_threshold";
- private static final String ATTR_DUCKED_TRACK_VOLUME = "ducking_volume";
- private static final String ATTR_GENERATED_IMAGE_CLIP = "generated_image_clip";
- private static final String ATTR_IS_IMAGE_CLIP_GENERATED = "is_image_clip_generated";
- private static final String ATTR_GENERATED_TRANSITION_CLIP = "generated_transition_clip";
- private static final String ATTR_IS_TRANSITION_GENERATED = "is_transition_generated";
- private static final String ATTR_OVERLAY_RGB_FILENAME = "overlay_rgb_filename";
- private static final String ATTR_OVERLAY_FRAME_WIDTH = "overlay_frame_width";
- private static final String ATTR_OVERLAY_FRAME_HEIGHT = "overlay_frame_height";
- private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH = "resized_RGBframe_width";
- private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT = "resized_RGBframe_height";
- private static final int ENGINE_ACCESS_MAX_TIMEOUT_MS = 500;
- /*
- * Instance variables
- */
- private final Semaphore mLock;
- private final String mProjectPath;
- private final List<MediaItem> mMediaItems = new ArrayList<MediaItem>();
- private final List<AudioTrack> mAudioTracks = new ArrayList<AudioTrack>();
- private final List<Transition> mTransitions = new ArrayList<Transition>();
- private long mDurationMs;
- private int mAspectRatio;
-
- /*
- * Private Object for calling native Methods via MediaArtistNativeHelper
- */
- private MediaArtistNativeHelper mMANativeHelper;
- private boolean mPreviewInProgress = false;
- private final boolean mMallocDebug;
-
- /**
- * Constructor
- *
- * @param projectPath - The path where the VideoEditor stores all files
- * related to the project
- */
- public VideoEditorImpl(String projectPath) throws IOException {
- String s;
- s = SystemProperties.get("libc.debug.malloc");
- if (s.equals("1")) {
- mMallocDebug = true;
- try {
- dumpHeap("HeapAtStart");
- } catch (Exception ex) {
- Log.e(TAG, "dumpHeap returned error in constructor");
- }
- } else {
- mMallocDebug = false;
- }
- mLock = new Semaphore(1, true);
- mMANativeHelper = new MediaArtistNativeHelper(projectPath, mLock, this);
- mProjectPath = projectPath;
- final File projectXml = new File(projectPath, PROJECT_FILENAME);
- if (projectXml.exists()) {
- try {
- load();
- } catch (Exception ex) {
- ex.printStackTrace();
- throw new IOException(ex.toString());
- }
- } else {
- mAspectRatio = MediaProperties.ASPECT_RATIO_16_9;
- mDurationMs = 0;
- }
- }
-
- /*
- * @return The MediaArtistNativeHelper object
- */
- MediaArtistNativeHelper getNativeContext() {
- return mMANativeHelper;
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void addAudioTrack(AudioTrack audioTrack) {
- if (audioTrack == null) {
- throw new IllegalArgumentException("Audio Track is null");
- }
-
- if (mAudioTracks.size() == 1) {
- throw new IllegalArgumentException("No more tracks can be added");
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- /*
- * Add the audio track to AudioTrack list
- */
- mAudioTracks.add(audioTrack);
-
- /*
- * Form the audio PCM file path
- */
- final String audioTrackPCMFilePath = String.format(mProjectPath + "/"
- + "AudioPcm" + audioTrack.getId() + ".pcm");
-
- /*
- * Create PCM only if not generated in previous session
- */
- if (new File(audioTrackPCMFilePath).exists()) {
- mMANativeHelper.setAudioflag(false);
- }
-
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void addMediaItem(MediaItem mediaItem) {
- /*
- * Validate Media Item
- */
- if (mediaItem == null) {
- throw new IllegalArgumentException("Media item is null");
- }
- /*
- * Add the Media item to MediaItem list
- */
- if (mMediaItems.contains(mediaItem)) {
- throw new IllegalArgumentException("Media item already exists: " + mediaItem.getId());
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- /*
- * Invalidate the end transition if necessary
- */
- final int mediaItemsCount = mMediaItems.size();
- if (mediaItemsCount > 0) {
- removeTransitionAfter(mediaItemsCount - 1);
- }
-
- /*
- * Add the new media item
- */
- mMediaItems.add(mediaItem);
-
- computeTimelineDuration();
-
- /*
- * Generate project thumbnail only from first media Item on storyboard
- */
- if (mMediaItems.size() == 1) {
- generateProjectThumbnail();
- }
- }
-
-
- /*
- * {@inheritDoc}
- */
- public synchronized void addTransition(Transition transition) {
- if (transition == null) {
- throw new IllegalArgumentException("Null Transition");
- }
-
- final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
- final MediaItem afterMediaItem = transition.getAfterMediaItem();
- /*
- * Check if the MediaItems are in sequence
- */
- if (mMediaItems == null) {
- throw new IllegalArgumentException("No media items are added");
- }
-
- if ((afterMediaItem != null) && (beforeMediaItem != null)) {
- final int afterMediaItemIndex = mMediaItems.indexOf(afterMediaItem);
- final int beforeMediaItemIndex = mMediaItems.indexOf(beforeMediaItem);
-
- if ((afterMediaItemIndex == -1) || (beforeMediaItemIndex == -1)) {
- throw new IllegalArgumentException
- ("Either of the mediaItem is not found in the list");
- }
-
- if (afterMediaItemIndex != (beforeMediaItemIndex - 1) ) {
- throw new IllegalArgumentException("MediaItems are not in sequence");
- }
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- mTransitions.add(transition);
- /*
- * Cross reference the transitions
- */
- if (afterMediaItem != null) {
- /*
- * If a transition already exists at the specified position then
- * invalidate it.
- */
- if (afterMediaItem.getEndTransition() != null) {
- afterMediaItem.getEndTransition().invalidate();
- mTransitions.remove(afterMediaItem.getEndTransition());
- }
- afterMediaItem.setEndTransition(transition);
- }
-
- if (beforeMediaItem != null) {
- /*
- * If a transition already exists at the specified position then
- * invalidate it.
- */
- if (beforeMediaItem.getBeginTransition() != null) {
- beforeMediaItem.getBeginTransition().invalidate();
- mTransitions.remove(beforeMediaItem.getBeginTransition());
- }
- beforeMediaItem.setBeginTransition(transition);
- }
-
- computeTimelineDuration();
- }
-
- /*
- * {@inheritDoc}
- */
- public void cancelExport(String filename) {
- if (mMANativeHelper != null && filename != null) {
- mMANativeHelper.stop(filename);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public void export(String filename, int height, int bitrate,
- int audioCodec, int videoCodec,
- ExportProgressListener listener)
- throws IOException {
- int audcodec = 0;
- int vidcodec = 0;
- if (filename == null) {
- throw new IllegalArgumentException("export: filename is null");
- }
-
- final File tempPathFile = new File(filename);
- if (tempPathFile == null) {
- throw new IOException(filename + "can not be created");
- }
-
- if (mMediaItems.size() == 0) {
- throw new IllegalStateException("No MediaItems added");
- }
-
- switch (height) {
- case MediaProperties.HEIGHT_144:
- break;
- case MediaProperties.HEIGHT_288:
- break;
- case MediaProperties.HEIGHT_360:
- break;
- case MediaProperties.HEIGHT_480:
- break;
- case MediaProperties.HEIGHT_720:
- break;
- case MediaProperties.HEIGHT_1080:
- break;
-
- default: {
- String message = "Unsupported height value " + height;
- throw new IllegalArgumentException(message);
- }
- }
-
- switch (bitrate) {
- case MediaProperties.BITRATE_28K:
- break;
- case MediaProperties.BITRATE_40K:
- break;
- case MediaProperties.BITRATE_64K:
- break;
- case MediaProperties.BITRATE_96K:
- break;
- case MediaProperties.BITRATE_128K:
- break;
- case MediaProperties.BITRATE_192K:
- break;
- case MediaProperties.BITRATE_256K:
- break;
- case MediaProperties.BITRATE_384K:
- break;
- case MediaProperties.BITRATE_512K:
- break;
- case MediaProperties.BITRATE_800K:
- break;
- case MediaProperties.BITRATE_2M:
- break;
- case MediaProperties.BITRATE_5M:
- break;
- case MediaProperties.BITRATE_8M:
- break;
-
- default: {
- final String message = "Unsupported bitrate value " + bitrate;
- throw new IllegalArgumentException(message);
- }
- }
- computeTimelineDuration();
- final long audioBitrate = MediaArtistNativeHelper.Bitrate.BR_96_KBPS;
- final long fileSize = (mDurationMs * (bitrate + audioBitrate)) / 8000;
- if (MAX_SUPPORTED_FILE_SIZE <= fileSize) {
- throw new IllegalStateException("Export Size is more than 2GB");
- }
- switch (audioCodec) {
- case MediaProperties.ACODEC_AAC_LC:
- audcodec = MediaArtistNativeHelper.AudioFormat.AAC;
- break;
- case MediaProperties.ACODEC_AMRNB:
- audcodec = MediaArtistNativeHelper.AudioFormat.AMR_NB;
- break;
-
- default: {
- String message = "Unsupported audio codec type " + audioCodec;
- throw new IllegalArgumentException(message);
- }
- }
-
- switch (videoCodec) {
- case MediaProperties.VCODEC_H263:
- vidcodec = MediaArtistNativeHelper.VideoFormat.H263;
- break;
- case MediaProperties.VCODEC_H264:
- vidcodec = MediaArtistNativeHelper.VideoFormat.H264;
- break;
- case MediaProperties.VCODEC_MPEG4:
- vidcodec = MediaArtistNativeHelper.VideoFormat.MPEG4;
- break;
-
- default: {
- String message = "Unsupported video codec type " + videoCodec;
- throw new IllegalArgumentException(message);
- }
- }
-
- boolean semAcquireDone = false;
- try {
- lock();
- semAcquireDone = true;
-
- if (mMANativeHelper == null) {
- throw new IllegalStateException("The video editor is not initialized");
- }
- mMANativeHelper.setAudioCodec(audcodec);
- mMANativeHelper.setVideoCodec(vidcodec);
- mMANativeHelper.export(filename, mProjectPath, height,bitrate,
- mMediaItems, mTransitions, mAudioTracks, listener);
- } catch (InterruptedException ex) {
- Log.e(TAG, "Sem acquire NOT successful in export");
- } finally {
- if (semAcquireDone) {
- unlock();
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public void export(String filename, int height, int bitrate,
- ExportProgressListener listener)
- throws IOException {
- int defaultAudiocodec = MediaArtistNativeHelper.AudioFormat.AAC;
- int defaultVideocodec = MediaArtistNativeHelper.VideoFormat.H264;
-
- export(filename, height, bitrate, defaultAudiocodec,
- defaultVideocodec, listener);
- }
-
- /*
- * {@inheritDoc}
- */
- public void generatePreview(MediaProcessingProgressListener listener) {
- boolean semAcquireDone = false;
- try {
- lock();
- semAcquireDone = true;
-
- if (mMANativeHelper == null) {
- throw new IllegalStateException("The video editor is not initialized");
- }
-
- if ((mMediaItems.size() > 0) || (mAudioTracks.size() > 0)) {
- mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions, mAudioTracks,
- listener);
- }
- } catch (InterruptedException ex) {
- Log.e(TAG, "Sem acquire NOT successful in previewStoryBoard");
- } finally {
- if (semAcquireDone) {
- unlock();
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public List<AudioTrack> getAllAudioTracks() {
- return mAudioTracks;
- }
-
- /*
- * {@inheritDoc}
- */
- public List<MediaItem> getAllMediaItems() {
- return mMediaItems;
- }
-
- /*
- * {@inheritDoc}
- */
- public List<Transition> getAllTransitions() {
- return mTransitions;
- }
-
- /*
- * {@inheritDoc}
- */
- public int getAspectRatio() {
- return mAspectRatio;
- }
-
- /*
- * {@inheritDoc}
- */
- public AudioTrack getAudioTrack(String audioTrackId) {
- for (AudioTrack at : mAudioTracks) {
- if (at.getId().equals(audioTrackId)) {
- return at;
- }
- }
- return null;
- }
-
- /*
- * {@inheritDoc}
- */
- public long getDuration() {
- /**
- * Since MediaImageItem can change duration we need to compute the
- * duration here
- */
- computeTimelineDuration();
- return mDurationMs;
- }
-
- /*
- * Force updates the timeline duration
- */
- void updateTimelineDuration() {
- computeTimelineDuration();
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized MediaItem getMediaItem(String mediaItemId) {
- for (MediaItem mediaItem : mMediaItems) {
- if (mediaItem.getId().equals(mediaItemId)) {
- return mediaItem;
- }
- }
- return null;
- }
-
- /*
- * {@inheritDoc}
- */
- public String getPath() {
- return mProjectPath;
- }
-
- /*
- * {@inheritDoc}
- */
- public Transition getTransition(String transitionId) {
- for (Transition transition : mTransitions) {
- if (transition.getId().equals(transitionId)) {
- return transition;
- }
- }
- return null;
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void insertAudioTrack(AudioTrack audioTrack,
- String afterAudioTrackId) {
- if (mAudioTracks.size() == 1) {
- throw new IllegalArgumentException("No more tracks can be added");
- }
-
- if (afterAudioTrackId == null) {
- mMANativeHelper.setGeneratePreview(true);
- mAudioTracks.add(0, audioTrack);
- } else {
- final int audioTrackCount = mAudioTracks.size();
- for (int i = 0; i < audioTrackCount; i++) {
- AudioTrack at = mAudioTracks.get(i);
- if (at.getId().equals(afterAudioTrackId)) {
- mMANativeHelper.setGeneratePreview(true);
- mAudioTracks.add(i + 1, audioTrack);
- return;
- }
- }
-
- throw new IllegalArgumentException("AudioTrack not found: " + afterAudioTrackId);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void insertMediaItem(MediaItem mediaItem, String afterMediaItemId) {
- if (mMediaItems.contains(mediaItem)) {
- throw new IllegalArgumentException("Media item already exists: " + mediaItem.getId());
- }
-
- if (afterMediaItemId == null) {
- mMANativeHelper.setGeneratePreview(true);
- if (mMediaItems.size() > 0) {
- /**
- * Invalidate the transition at the beginning of the timeline
- */
- removeTransitionBefore(0);
- }
-
- mMediaItems.add(0, mediaItem);
- computeTimelineDuration();
- generateProjectThumbnail();
- } else {
- final int mediaItemCount = mMediaItems.size();
- for (int i = 0; i < mediaItemCount; i++) {
- final MediaItem mi = mMediaItems.get(i);
- if (mi.getId().equals(afterMediaItemId)) {
- mMANativeHelper.setGeneratePreview(true);
- /**
- * Invalidate the transition at this position
- */
- removeTransitionAfter(i);
- /**
- * Insert the new media item
- */
- mMediaItems.add(i + 1, mediaItem);
- computeTimelineDuration();
- return;
- }
- }
-
- throw new IllegalArgumentException("MediaItem not found: " + afterMediaItemId);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void moveAudioTrack(String audioTrackId, String afterAudioTrackId) {
- throw new IllegalStateException("Not supported");
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void moveMediaItem(String mediaItemId, String afterMediaItemId) {
- final MediaItem moveMediaItem = removeMediaItem(mediaItemId,true);
- if (moveMediaItem == null) {
- throw new IllegalArgumentException("Target MediaItem not found: " + mediaItemId);
- }
-
- if (afterMediaItemId == null) {
- if (mMediaItems.size() > 0) {
- mMANativeHelper.setGeneratePreview(true);
-
- /**
- * Invalidate adjacent transitions at the insertion point
- */
- removeTransitionBefore(0);
-
- /**
- * Insert the media item at the new position
- */
- mMediaItems.add(0, moveMediaItem);
- computeTimelineDuration();
-
- generateProjectThumbnail();
- } else {
- throw new IllegalStateException("Cannot move media item (it is the only item)");
- }
- } else {
- final int mediaItemCount = mMediaItems.size();
- for (int i = 0; i < mediaItemCount; i++) {
- final MediaItem mi = mMediaItems.get(i);
- if (mi.getId().equals(afterMediaItemId)) {
- mMANativeHelper.setGeneratePreview(true);
- /**
- * Invalidate adjacent transitions at the insertion point
- */
- removeTransitionAfter(i);
- /**
- * Insert the media item at the new position
- */
- mMediaItems.add(i + 1, moveMediaItem);
- computeTimelineDuration();
- return;
- }
- }
-
- throw new IllegalArgumentException("MediaItem not found: " + afterMediaItemId);
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public void release() {
- stopPreview();
-
- boolean semAcquireDone = false;
- try {
- lock();
- semAcquireDone = true;
-
- if (mMANativeHelper != null) {
- mMediaItems.clear();
- mAudioTracks.clear();
- mTransitions.clear();
- mMANativeHelper.releaseNativeHelper();
- mMANativeHelper = null;
- }
- } catch (Exception ex) {
- Log.e(TAG, "Sem acquire NOT successful in export", ex);
- } finally {
- if (semAcquireDone) {
- unlock();
- }
- }
- if (mMallocDebug) {
- try {
- dumpHeap("HeapAtEnd");
- } catch (Exception ex) {
- Log.e(TAG, "dumpHeap returned error in release");
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized void removeAllMediaItems() {
- mMANativeHelper.setGeneratePreview(true);
-
- mMediaItems.clear();
-
- /**
- * Invalidate all transitions
- */
- for (Transition transition : mTransitions) {
- transition.invalidate();
- }
- mTransitions.clear();
-
- mDurationMs = 0;
- /**
- * If a thumbnail already exists, then delete it
- */
- if ((new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).exists()) {
- (new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).delete();
- }
-
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized AudioTrack removeAudioTrack(String audioTrackId) {
- final AudioTrack audioTrack = getAudioTrack(audioTrackId);
- if (audioTrack != null) {
- mMANativeHelper.setGeneratePreview(true);
- mAudioTracks.remove(audioTrack);
- audioTrack.invalidate();
- mMANativeHelper.invalidatePcmFile();
- mMANativeHelper.setAudioflag(true);
- } else {
- throw new IllegalArgumentException(" No more audio tracks");
- }
- return audioTrack;
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized MediaItem removeMediaItem(String mediaItemId) {
- final String firstItemString = mMediaItems.get(0).getId();
- final MediaItem mediaItem = getMediaItem(mediaItemId);
- if (mediaItem != null) {
- mMANativeHelper.setGeneratePreview(true);
- /**
- * Remove the media item
- */
- mMediaItems.remove(mediaItem);
- if (mediaItem instanceof MediaImageItem) {
- ((MediaImageItem)mediaItem).invalidate();
- }
- final List<Overlay> overlays = mediaItem.getAllOverlays();
- if (overlays.size() > 0) {
- for (Overlay overlay : overlays) {
- if (overlay instanceof OverlayFrame) {
- final OverlayFrame overlayFrame = (OverlayFrame)overlay;
- overlayFrame.invalidate();
- }
- }
- }
-
- /**
- * Remove the adjacent transitions
- */
- removeAdjacentTransitions(mediaItem);
- computeTimelineDuration();
- }
-
- /**
- * If string equals first mediaItem, then
- * generate Project thumbnail
- */
- if (firstItemString.equals(mediaItemId)) {
- generateProjectThumbnail();
- }
-
- if (mediaItem instanceof MediaVideoItem) {
- /**
- * Delete the graph file
- */
- ((MediaVideoItem)mediaItem).invalidate();
- }
- return mediaItem;
- }
-
- private synchronized MediaItem removeMediaItem(String mediaItemId, boolean flag) {
- final String firstItemString = mMediaItems.get(0).getId();
-
- final MediaItem mediaItem = getMediaItem(mediaItemId);
- if (mediaItem != null) {
- mMANativeHelper.setGeneratePreview(true);
- /**
- * Remove the media item
- */
- mMediaItems.remove(mediaItem);
- /**
- * Remove the adjacent transitions
- */
- removeAdjacentTransitions(mediaItem);
- computeTimelineDuration();
- }
-
- /**
- * If string equals first mediaItem, then
- * generate Project thumbail
- */
- if (firstItemString.equals(mediaItemId)) {
- generateProjectThumbnail();
- }
- return mediaItem;
- }
-
- /*
- * {@inheritDoc}
- */
- public synchronized Transition removeTransition(String transitionId) {
- final Transition transition = getTransition(transitionId);
- if (transition == null) {
- throw new IllegalStateException("Transition not found: " + transitionId);
- }
-
- mMANativeHelper.setGeneratePreview(true);
-
- /**
- * Remove the transition references
- */
- final MediaItem afterMediaItem = transition.getAfterMediaItem();
- if (afterMediaItem != null) {
- afterMediaItem.setEndTransition(null);
- }
-
- final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
- if (beforeMediaItem != null) {
- beforeMediaItem.setBeginTransition(null);
- }
-
- mTransitions.remove(transition);
- transition.invalidate();
- computeTimelineDuration();
- return transition;
- }
-
- /*
- * {@inheritDoc}
- */
- public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
- OverlayData overlayData) {
- if (surfaceHolder == null) {
- throw new IllegalArgumentException("Surface Holder is null");
- }
-
- final Surface surface = surfaceHolder.getSurface();
- if (surface == null) {
- throw new IllegalArgumentException("Surface could not be retrieved from Surface holder");
- }
-
- if (surface.isValid() == false) {
- throw new IllegalStateException("Surface is not valid");
- }
-
- if (timeMs < 0) {
- throw new IllegalArgumentException("requested time not correct");
- } else if (timeMs > mDurationMs) {
- throw new IllegalArgumentException("requested time more than duration");
- }
- long result = 0;
-
- boolean semAcquireDone = false;
- try {
- semAcquireDone = lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
- if (semAcquireDone == false) {
- throw new IllegalStateException("Timeout waiting for semaphore");
- }
-
- if (mMANativeHelper == null) {
- throw new IllegalStateException("The video editor is not initialized");
- }
-
- if (mMediaItems.size() > 0) {
- final Rect frame = surfaceHolder.getSurfaceFrame();
- result = mMANativeHelper.renderPreviewFrame(surface,
- timeMs, frame.width(), frame.height(), overlayData);
- } else {
- result = 0;
- }
- } catch (InterruptedException ex) {
- Log.w(TAG, "The thread was interrupted", new Throwable());
- throw new IllegalStateException("The thread was interrupted");
- } finally {
- if (semAcquireDone) {
- unlock();
- }
- }
- return result;
- }
-
- /**
- * the project form XML
- */
- private void load() throws FileNotFoundException, XmlPullParserException, IOException {
- final File file = new File(mProjectPath, PROJECT_FILENAME);
- /**
- * Load the metadata
- */
- final FileInputStream fis = new FileInputStream(file);
- try {
- final List<String> ignoredMediaItems = new ArrayList<String>();
-
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(fis, "UTF-8");
- int eventType = parser.getEventType();
- String name;
- MediaItem currentMediaItem = null;
- Overlay currentOverlay = null;
- boolean regenerateProjectThumbnail = false;
- while (eventType != XmlPullParser.END_DOCUMENT) {
- switch (eventType) {
- case XmlPullParser.START_TAG: {
- name = parser.getName();
- if (TAG_PROJECT.equals(name)) {
- mAspectRatio = Integer.parseInt(parser.getAttributeValue("",
- ATTR_ASPECT_RATIO));
-
- final boolean mRegenPCM =
- Boolean.parseBoolean(parser.getAttributeValue("",
- ATTR_REGENERATE_PCM));
- mMANativeHelper.setAudioflag(mRegenPCM);
- } else if (TAG_MEDIA_ITEM.equals(name)) {
- final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
- try {
- currentMediaItem = parseMediaItem(parser);
- mMediaItems.add(currentMediaItem);
- } catch (Exception ex) {
- Log.w(TAG, "Cannot load media item: " + mediaItemId, ex);
- currentMediaItem = null;
-
- // First media item is invalid, mark for project thumbnail removal
- if (mMediaItems.size() == 0) {
- regenerateProjectThumbnail = true;
- }
- // Ignore the media item
- ignoredMediaItems.add(mediaItemId);
- }
- } else if (TAG_TRANSITION.equals(name)) {
- try {
- final Transition transition = parseTransition(parser,
- ignoredMediaItems);
- // The transition will be null if the bounding
- // media items are ignored
- if (transition != null) {
- mTransitions.add(transition);
- }
- } catch (Exception ex) {
- Log.w(TAG, "Cannot load transition", ex);
- }
- } else if (TAG_OVERLAY.equals(name)) {
- if (currentMediaItem != null) {
- try {
- currentOverlay = parseOverlay(parser, currentMediaItem);
- currentMediaItem.addOverlay(currentOverlay);
- } catch (Exception ex) {
- Log.w(TAG, "Cannot load overlay", ex);
- }
- }
- } else if (TAG_OVERLAY_USER_ATTRIBUTES.equals(name)) {
- if (currentOverlay != null) {
- final int attributesCount = parser.getAttributeCount();
- for (int i = 0; i < attributesCount; i++) {
- currentOverlay.setUserAttribute(parser.getAttributeName(i),
- parser.getAttributeValue(i));
- }
- }
- } else if (TAG_EFFECT.equals(name)) {
- if (currentMediaItem != null) {
- try {
- final Effect effect = parseEffect(parser, currentMediaItem);
- currentMediaItem.addEffect(effect);
-
- if (effect instanceof EffectKenBurns) {
- final boolean isImageClipGenerated =
- Boolean.parseBoolean(parser.getAttributeValue("",
- ATTR_IS_IMAGE_CLIP_GENERATED));
- if(isImageClipGenerated) {
- final String filename = parser.getAttributeValue("",
- ATTR_GENERATED_IMAGE_CLIP);
- if (new File(filename).exists() == true) {
- ((MediaImageItem)currentMediaItem).
- setGeneratedImageClip(filename);
- ((MediaImageItem)currentMediaItem).
- setRegenerateClip(false);
- } else {
- ((MediaImageItem)currentMediaItem).
- setGeneratedImageClip(null);
- ((MediaImageItem)currentMediaItem).
- setRegenerateClip(true);
- }
- } else {
- ((MediaImageItem)currentMediaItem).
- setGeneratedImageClip(null);
- ((MediaImageItem)currentMediaItem).
- setRegenerateClip(true);
- }
- }
- } catch (Exception ex) {
- Log.w(TAG, "Cannot load effect", ex);
- }
- }
- } else if (TAG_AUDIO_TRACK.equals(name)) {
- try {
- final AudioTrack audioTrack = parseAudioTrack(parser);
- addAudioTrack(audioTrack);
- } catch (Exception ex) {
- Log.w(TAG, "Cannot load audio track", ex);
- }
- }
- break;
- }
-
- case XmlPullParser.END_TAG: {
- name = parser.getName();
- if (TAG_MEDIA_ITEM.equals(name)) {
- currentMediaItem = null;
- } else if (TAG_OVERLAY.equals(name)) {
- currentOverlay = null;
- }
- break;
- }
-
- default: {
- break;
- }
- }
- eventType = parser.next();
- }
- computeTimelineDuration();
- // Regenerate project thumbnail
- if (regenerateProjectThumbnail) {
- generateProjectThumbnail();
- regenerateProjectThumbnail = false;
- }
- } finally {
- if (fis != null) {
- fis.close();
- }
- }
- }
-
- /**
- * Parse the media item
- *
- * @param parser The parser
- * @return The media item
- */
- private MediaItem parseMediaItem(XmlPullParser parser) throws IOException {
- final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
- final String type = parser.getAttributeValue("", ATTR_TYPE);
- final String filename = parser.getAttributeValue("", ATTR_FILENAME);
- final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
- ATTR_RENDERING_MODE));
-
- final MediaItem currentMediaItem;
- if (MediaImageItem.class.getSimpleName().equals(type)) {
- final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
- currentMediaItem = new MediaImageItem(this, mediaItemId, filename,
- durationMs, renderingMode);
- } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
- final long beginMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
- final long endMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
- final int volume = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
- final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_MUTED));
- final String audioWaveformFilename = parser.getAttributeValue("",
- ATTR_AUDIO_WAVEFORM_FILENAME);
- currentMediaItem = new MediaVideoItem(this, mediaItemId, filename,
- renderingMode, beginMs, endMs, volume, muted, audioWaveformFilename);
-
- final long beginTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
- final long endTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
- ((MediaVideoItem)currentMediaItem).setExtractBoundaries(beginTimeMs, endTimeMs);
-
- final int volumePercent = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
- ((MediaVideoItem)currentMediaItem).setVolume(volumePercent);
- } else {
- throw new IllegalArgumentException("Unknown media item type: " + type);
- }
-
- return currentMediaItem;
- }
-
- /**
- * Parse the transition
- *
- * @param parser The parser
- * @param ignoredMediaItems The list of ignored media items
- *
- * @return The transition
- */
- private Transition parseTransition(XmlPullParser parser, List<String> ignoredMediaItems) {
- final String transitionId = parser.getAttributeValue("", ATTR_ID);
- final String type = parser.getAttributeValue("", ATTR_TYPE);
- final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
- final int behavior = Integer.parseInt(parser.getAttributeValue("", ATTR_BEHAVIOR));
-
- final String beforeMediaItemId = parser.getAttributeValue("", ATTR_BEFORE_MEDIA_ITEM_ID);
- final MediaItem beforeMediaItem;
- if (beforeMediaItemId != null) {
- if (ignoredMediaItems.contains(beforeMediaItemId)) {
- // This transition is ignored
- return null;
- }
-
- beforeMediaItem = getMediaItem(beforeMediaItemId);
- } else {
- beforeMediaItem = null;
- }
-
- final String afterMediaItemId = parser.getAttributeValue("", ATTR_AFTER_MEDIA_ITEM_ID);
- final MediaItem afterMediaItem;
- if (afterMediaItemId != null) {
- if (ignoredMediaItems.contains(afterMediaItemId)) {
- // This transition is ignored
- return null;
- }
-
- afterMediaItem = getMediaItem(afterMediaItemId);
- } else {
- afterMediaItem = null;
- }
-
- final Transition transition;
- if (TransitionAlpha.class.getSimpleName().equals(type)) {
- final int blending = Integer.parseInt(parser.getAttributeValue("", ATTR_BLENDING));
- final String maskFilename = parser.getAttributeValue("", ATTR_MASK);
- final boolean invert = Boolean.getBoolean(parser.getAttributeValue("", ATTR_INVERT));
- transition = new TransitionAlpha(transitionId, afterMediaItem, beforeMediaItem,
- durationMs, behavior, maskFilename, blending, invert);
- } else if (TransitionCrossfade.class.getSimpleName().equals(type)) {
- transition = new TransitionCrossfade(transitionId, afterMediaItem, beforeMediaItem,
- durationMs, behavior);
- } else if (TransitionSliding.class.getSimpleName().equals(type)) {
- final int direction = Integer.parseInt(parser.getAttributeValue("", ATTR_DIRECTION));
- transition = new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem,
- durationMs, behavior, direction);
- } else if (TransitionFadeBlack.class.getSimpleName().equals(type)) {
- transition = new TransitionFadeBlack(transitionId, afterMediaItem, beforeMediaItem,
- durationMs, behavior);
- } else {
- throw new IllegalArgumentException("Invalid transition type: " + type);
- }
-
- final boolean isTransitionGenerated = Boolean.parseBoolean(parser.getAttributeValue("",
- ATTR_IS_TRANSITION_GENERATED));
- if (isTransitionGenerated == true) {
- final String transitionFile = parser.getAttributeValue("",
- ATTR_GENERATED_TRANSITION_CLIP);
-
- if (new File(transitionFile).exists()) {
- transition.setFilename(transitionFile);
- } else {
- transition.setFilename(null);
- }
- }
-
- // Use the transition
- if (beforeMediaItem != null) {
- beforeMediaItem.setBeginTransition(transition);
- }
-
- if (afterMediaItem != null) {
- afterMediaItem.setEndTransition(transition);
- }
-
- return transition;
- }
-
- /**
- * Parse the overlay
- *
- * @param parser The parser
- * @param mediaItem The media item owner
- *
- * @return The overlay
- */
- private Overlay parseOverlay(XmlPullParser parser, MediaItem mediaItem) {
- final String overlayId = parser.getAttributeValue("", ATTR_ID);
- final String type = parser.getAttributeValue("", ATTR_TYPE);
- final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
- final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-
- final Overlay overlay;
- if (OverlayFrame.class.getSimpleName().equals(type)) {
- final String filename = parser.getAttributeValue("", ATTR_FILENAME);
- overlay = new OverlayFrame(mediaItem, overlayId, filename, startTimeMs, durationMs);
- } else {
- throw new IllegalArgumentException("Invalid overlay type: " + type);
- }
-
- final String overlayRgbFileName = parser.getAttributeValue("", ATTR_OVERLAY_RGB_FILENAME);
- if (overlayRgbFileName != null) {
- ((OverlayFrame)overlay).setFilename(overlayRgbFileName);
-
- final int overlayFrameWidth = Integer.parseInt(parser.getAttributeValue("",
- ATTR_OVERLAY_FRAME_WIDTH));
- final int overlayFrameHeight = Integer.parseInt(parser.getAttributeValue("",
- ATTR_OVERLAY_FRAME_HEIGHT));
-
- ((OverlayFrame)overlay).setOverlayFrameWidth(overlayFrameWidth);
- ((OverlayFrame)overlay).setOverlayFrameHeight(overlayFrameHeight);
-
- final int resizedRGBFrameWidth = Integer.parseInt(parser.getAttributeValue("",
- ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH));
- final int resizedRGBFrameHeight = Integer.parseInt(parser.getAttributeValue("",
- ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT));
-
- ((OverlayFrame)overlay).setResizedRGBSize(resizedRGBFrameWidth, resizedRGBFrameHeight);
- }
-
- return overlay;
- }
-
- /**
- * Parse the effect
- *
- * @param parser The parser
- * @param mediaItem The media item owner
- *
- * @return The effect
- */
- private Effect parseEffect(XmlPullParser parser, MediaItem mediaItem) {
- final String effectId = parser.getAttributeValue("", ATTR_ID);
- final String type = parser.getAttributeValue("", ATTR_TYPE);
- final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
- final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-
- final Effect effect;
- if (EffectColor.class.getSimpleName().equals(type)) {
- final int colorEffectType = Integer.parseInt(parser.getAttributeValue("",
- ATTR_COLOR_EFFECT_TYPE));
- final int color;
- if (colorEffectType == EffectColor.TYPE_COLOR
- || colorEffectType == EffectColor.TYPE_GRADIENT) {
- color = Integer.parseInt(parser.getAttributeValue("", ATTR_COLOR_EFFECT_VALUE));
- } else {
- color = 0;
- }
- effect = new EffectColor(mediaItem, effectId, startTimeMs,
- durationMs, colorEffectType, color);
- } else if (EffectKenBurns.class.getSimpleName().equals(type)) {
- final Rect startRect = new Rect(
- Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_LEFT)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_TOP)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_RIGHT)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_BOTTOM)));
- final Rect endRect = new Rect(
- Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_LEFT)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_TOP)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_RIGHT)),
- Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_BOTTOM)));
- effect = new EffectKenBurns(mediaItem, effectId, startRect, endRect,
- startTimeMs, durationMs);
- } else {
- throw new IllegalArgumentException("Invalid effect type: " + type);
- }
-
- return effect;
- }
-
- /**
- * Parse the audio track
- *
- * @param parser The parser
- *
- * @return The audio track
- */
- private AudioTrack parseAudioTrack(XmlPullParser parser) throws IOException {
- final String audioTrackId = parser.getAttributeValue("", ATTR_ID);
- final String filename = parser.getAttributeValue("", ATTR_FILENAME);
- final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_START_TIME));
- final long beginMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
- final long endMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
- final int volume = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
- final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_MUTED));
- final boolean loop = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_LOOP));
- final boolean duckingEnabled = Boolean.parseBoolean(
- parser.getAttributeValue("", ATTR_DUCK_ENABLED));
- final int duckThreshold = Integer.parseInt(
- parser.getAttributeValue("", ATTR_DUCK_THRESHOLD));
- final int duckedTrackVolume = Integer.parseInt(parser.getAttributeValue("",
- ATTR_DUCKED_TRACK_VOLUME));
-
- final String waveformFilename = parser.getAttributeValue("", ATTR_AUDIO_WAVEFORM_FILENAME);
- final AudioTrack audioTrack = new AudioTrack(this, audioTrackId,
- filename, startTimeMs,
- beginMs, endMs, loop,
- volume, muted,
- duckingEnabled,
- duckThreshold,
- duckedTrackVolume,
- waveformFilename);
-
- return audioTrack;
- }
-
- /*
- * {@inheritDoc}
- */
- public void save() throws IOException {
- final XmlSerializer serializer = Xml.newSerializer();
- final StringWriter writer = new StringWriter();
- serializer.setOutput(writer);
- serializer.startDocument("UTF-8", true);
- serializer.startTag("", TAG_PROJECT);
- serializer.attribute("",
- ATTR_ASPECT_RATIO, Integer.toString(mAspectRatio));
-
- serializer.attribute("", ATTR_REGENERATE_PCM,
- Boolean.toString(mMANativeHelper.getAudioflag()));
-
- serializer.startTag("", TAG_MEDIA_ITEMS);
- for (MediaItem mediaItem : mMediaItems) {
- serializer.startTag("", TAG_MEDIA_ITEM);
- serializer.attribute("", ATTR_ID, mediaItem.getId());
- serializer.attribute("", ATTR_TYPE,
- mediaItem.getClass().getSimpleName());
- serializer.attribute("", ATTR_FILENAME, mediaItem.getFilename());
- serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(
- mediaItem.getRenderingMode()));
- if (mediaItem instanceof MediaVideoItem) {
- final MediaVideoItem mvi = (MediaVideoItem)mediaItem;
- serializer
- .attribute("", ATTR_BEGIN_TIME,
- Long.toString(mvi.getBoundaryBeginTime()));
- serializer.attribute("", ATTR_END_TIME,
- Long.toString(mvi.getBoundaryEndTime()));
- serializer.attribute("", ATTR_VOLUME,
- Integer.toString(mvi.getVolume()));
- serializer.attribute("", ATTR_MUTED,
- Boolean.toString(mvi.isMuted()));
- if (mvi.getAudioWaveformFilename() != null) {
- serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
- mvi.getAudioWaveformFilename());
- }
- } else if (mediaItem instanceof MediaImageItem) {
- serializer.attribute("", ATTR_DURATION,
- Long.toString(mediaItem.getTimelineDuration()));
- }
-
- final List<Overlay> overlays = mediaItem.getAllOverlays();
- if (overlays.size() > 0) {
- serializer.startTag("", TAG_OVERLAYS);
- for (Overlay overlay : overlays) {
- serializer.startTag("", TAG_OVERLAY);
- serializer.attribute("", ATTR_ID, overlay.getId());
- serializer.attribute("",
- ATTR_TYPE, overlay.getClass().getSimpleName());
- serializer.attribute("", ATTR_BEGIN_TIME,
- Long.toString(overlay.getStartTime()));
- serializer.attribute("", ATTR_DURATION,
- Long.toString(overlay.getDuration()));
- if (overlay instanceof OverlayFrame) {
- final OverlayFrame overlayFrame = (OverlayFrame)overlay;
- overlayFrame.save(getPath());
- if (overlayFrame.getBitmapImageFileName() != null) {
- serializer.attribute("", ATTR_FILENAME,
- overlayFrame.getBitmapImageFileName());
- }
-
- if (overlayFrame.getFilename() != null) {
- serializer.attribute("",
- ATTR_OVERLAY_RGB_FILENAME,
- overlayFrame.getFilename());
- serializer.attribute("", ATTR_OVERLAY_FRAME_WIDTH,
- Integer.toString(overlayFrame.getOverlayFrameWidth()));
- serializer.attribute("", ATTR_OVERLAY_FRAME_HEIGHT,
- Integer.toString(overlayFrame.getOverlayFrameHeight()));
- serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH,
- Integer.toString(overlayFrame.getResizedRGBSizeWidth()));
- serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT,
- Integer.toString(overlayFrame.getResizedRGBSizeHeight()));
-
- }
-
- }
-
- /**
- * Save the user attributes
- */
- serializer.startTag("", TAG_OVERLAY_USER_ATTRIBUTES);
- final Map<String, String> userAttributes = overlay.getUserAttributes();
- for (String name : userAttributes.keySet()) {
- final String value = userAttributes.get(name);
- if (value != null) {
- serializer.attribute("", name, value);
- }
- }
- serializer.endTag("", TAG_OVERLAY_USER_ATTRIBUTES);
-
- serializer.endTag("", TAG_OVERLAY);
- }
- serializer.endTag("", TAG_OVERLAYS);
- }
-
- final List<Effect> effects = mediaItem.getAllEffects();
- if (effects.size() > 0) {
- serializer.startTag("", TAG_EFFECTS);
- for (Effect effect : effects) {
- serializer.startTag("", TAG_EFFECT);
- serializer.attribute("", ATTR_ID, effect.getId());
- serializer.attribute("",
- ATTR_TYPE, effect.getClass().getSimpleName());
- serializer.attribute("", ATTR_BEGIN_TIME,
- Long.toString(effect.getStartTime()));
- serializer.attribute("", ATTR_DURATION,
- Long.toString(effect.getDuration()));
- if (effect instanceof EffectColor) {
- final EffectColor colorEffect = (EffectColor)effect;
- serializer.attribute("", ATTR_COLOR_EFFECT_TYPE,
- Integer.toString(colorEffect.getType()));
- if (colorEffect.getType() == EffectColor.TYPE_COLOR ||
- colorEffect.getType() == EffectColor.TYPE_GRADIENT) {
- serializer.attribute("", ATTR_COLOR_EFFECT_VALUE,
- Integer.toString(colorEffect.getColor()));
- }
- } else if (effect instanceof EffectKenBurns) {
- final Rect startRect = ((EffectKenBurns)effect).getStartRect();
- serializer.attribute("", ATTR_START_RECT_LEFT,
- Integer.toString(startRect.left));
- serializer.attribute("", ATTR_START_RECT_TOP,
- Integer.toString(startRect.top));
- serializer.attribute("", ATTR_START_RECT_RIGHT,
- Integer.toString(startRect.right));
- serializer.attribute("", ATTR_START_RECT_BOTTOM,
- Integer.toString(startRect.bottom));
-
- final Rect endRect = ((EffectKenBurns)effect).getEndRect();
- serializer.attribute("", ATTR_END_RECT_LEFT,
- Integer.toString(endRect.left));
- serializer.attribute("", ATTR_END_RECT_TOP,
- Integer.toString(endRect.top));
- serializer.attribute("", ATTR_END_RECT_RIGHT,
- Integer.toString(endRect.right));
- serializer.attribute("", ATTR_END_RECT_BOTTOM,
- Integer.toString(endRect.bottom));
- final MediaItem mItem = effect.getMediaItem();
- if(((MediaImageItem)mItem).getGeneratedImageClip() != null) {
- serializer.attribute("", ATTR_IS_IMAGE_CLIP_GENERATED,
- Boolean.toString(true));
- serializer.attribute("", ATTR_GENERATED_IMAGE_CLIP,
- ((MediaImageItem)mItem).getGeneratedImageClip());
- } else {
- serializer.attribute("", ATTR_IS_IMAGE_CLIP_GENERATED,
- Boolean.toString(false));
- }
- }
-
- serializer.endTag("", TAG_EFFECT);
- }
- serializer.endTag("", TAG_EFFECTS);
- }
-
- serializer.endTag("", TAG_MEDIA_ITEM);
- }
- serializer.endTag("", TAG_MEDIA_ITEMS);
-
- serializer.startTag("", TAG_TRANSITIONS);
-
- for (Transition transition : mTransitions) {
- serializer.startTag("", TAG_TRANSITION);
- serializer.attribute("", ATTR_ID, transition.getId());
- serializer.attribute("", ATTR_TYPE, transition.getClass().getSimpleName());
- serializer.attribute("", ATTR_DURATION, Long.toString(transition.getDuration()));
- serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(transition.getBehavior()));
- serializer.attribute("", ATTR_IS_TRANSITION_GENERATED,
- Boolean.toString(transition.isGenerated()));
- if (transition.isGenerated() == true) {
- serializer.attribute("", ATTR_GENERATED_TRANSITION_CLIP, transition.mFilename);
- }
- final MediaItem afterMediaItem = transition.getAfterMediaItem();
- if (afterMediaItem != null) {
- serializer.attribute("", ATTR_AFTER_MEDIA_ITEM_ID, afterMediaItem.getId());
- }
-
- final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
- if (beforeMediaItem != null) {
- serializer.attribute("", ATTR_BEFORE_MEDIA_ITEM_ID, beforeMediaItem.getId());
- }
-
- if (transition instanceof TransitionSliding) {
- serializer.attribute("", ATTR_DIRECTION,
- Integer.toString(((TransitionSliding)transition).getDirection()));
- } else if (transition instanceof TransitionAlpha) {
- TransitionAlpha ta = (TransitionAlpha)transition;
- serializer.attribute("", ATTR_BLENDING,
- Integer.toString(ta.getBlendingPercent()));
- serializer.attribute("", ATTR_INVERT,
- Boolean.toString(ta.isInvert()));
- if (ta.getMaskFilename() != null) {
- serializer.attribute("", ATTR_MASK, ta.getMaskFilename());
- }
- }
- serializer.endTag("", TAG_TRANSITION);
- }
- serializer.endTag("", TAG_TRANSITIONS);
- serializer.startTag("", TAG_AUDIO_TRACKS);
- for (AudioTrack at : mAudioTracks) {
- serializer.startTag("", TAG_AUDIO_TRACK);
- serializer.attribute("", ATTR_ID, at.getId());
- serializer.attribute("", ATTR_FILENAME, at.getFilename());
- serializer.attribute("", ATTR_START_TIME, Long.toString(at.getStartTime()));
- serializer.attribute("", ATTR_BEGIN_TIME, Long.toString(at.getBoundaryBeginTime()));
- serializer.attribute("", ATTR_END_TIME, Long.toString(at.getBoundaryEndTime()));
- serializer.attribute("", ATTR_VOLUME, Integer.toString(at.getVolume()));
- serializer.attribute("", ATTR_DUCK_ENABLED,
- Boolean.toString(at.isDuckingEnabled()));
- serializer.attribute("", ATTR_DUCKED_TRACK_VOLUME,
- Integer.toString(at.getDuckedTrackVolume()));
- serializer.attribute("", ATTR_DUCK_THRESHOLD,
- Integer.toString(at.getDuckingThreshhold()));
- serializer.attribute("", ATTR_MUTED, Boolean.toString(at.isMuted()));
- serializer.attribute("", ATTR_LOOP, Boolean.toString(at.isLooping()));
- if (at.getAudioWaveformFilename() != null) {
- serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
- at.getAudioWaveformFilename());
- }
-
- serializer.endTag("", TAG_AUDIO_TRACK);
- }
- serializer.endTag("", TAG_AUDIO_TRACKS);
-
- serializer.endTag("", TAG_PROJECT);
- serializer.endDocument();
-
- /**
- * Save the metadata XML file
- */
- final FileOutputStream out = new FileOutputStream(new File(getPath(),
- PROJECT_FILENAME));
- out.write(writer.toString().getBytes());
- out.flush();
- out.close();
- }
-
- /*
- * {@inheritDoc}
- */
- public void setAspectRatio(int aspectRatio) {
- mAspectRatio = aspectRatio;
- /**
- * Invalidate all transitions
- */
- mMANativeHelper.setGeneratePreview(true);
-
- for (Transition transition : mTransitions) {
- transition.invalidate();
- }
-
- final Iterator<MediaItem> it = mMediaItems.iterator();
-
- while (it.hasNext()) {
- final MediaItem t = it.next();
- List<Overlay> overlayList = t.getAllOverlays();
- for (Overlay overlay : overlayList) {
-
- ((OverlayFrame)overlay).invalidateGeneratedFiles();
- }
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs,
- boolean loop, int callbackAfterFrameCount,
- PreviewProgressListener listener) {
-
- if (surfaceHolder == null) {
- throw new IllegalArgumentException();
- }
-
- final Surface surface = surfaceHolder.getSurface();
- if (surface == null) {
- throw new IllegalArgumentException("Surface could not be retrieved from surface holder");
- }
-
- if (surface.isValid() == false) {
- throw new IllegalStateException("Surface is not valid");
- }
-
- if (listener == null) {
- throw new IllegalArgumentException();
- }
-
- if (fromMs >= mDurationMs) {
- throw new IllegalArgumentException("Requested time not correct");
- }
-
- if (fromMs < 0) {
- throw new IllegalArgumentException("Requested time not correct");
- }
-
- boolean semAcquireDone = false;
- if (!mPreviewInProgress) {
- try{
- semAcquireDone = lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
- if (semAcquireDone == false) {
- throw new IllegalStateException("Timeout waiting for semaphore");
- }
-
- if (mMANativeHelper == null) {
- throw new IllegalStateException("The video editor is not initialized");
- }
-
- if (mMediaItems.size() > 0) {
- mPreviewInProgress = true;
- mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions,
- mAudioTracks, null);
- mMANativeHelper.doPreview(surface, fromMs, toMs, loop,
- callbackAfterFrameCount, listener);
- }
- /**
- * Release The lock on complete by calling stopPreview
- */
- } catch (InterruptedException ex) {
- Log.w(TAG, "The thread was interrupted", new Throwable());
- throw new IllegalStateException("The thread was interrupted");
- }
- } else {
- throw new IllegalStateException("Preview already in progress");
- }
- }
-
- /*
- * {@inheritDoc}
- */
- public long stopPreview() {
- long result = 0;
- if (mPreviewInProgress) {
- try {
- result = mMANativeHelper.stopPreview();
- /**
- * release on complete by calling stopPreview
- */
- } finally {
- mPreviewInProgress = false;
- unlock();
- }
- return result;
- }
- else {
- return 0;
- }
- }
-
- /*
- * Remove transitions associated with the specified media item
- *
- * @param mediaItem The media item
- */
- private void removeAdjacentTransitions(MediaItem mediaItem) {
- final Transition beginTransition = mediaItem.getBeginTransition();
- if (beginTransition != null) {
- if (beginTransition.getAfterMediaItem() != null) {
- beginTransition.getAfterMediaItem().setEndTransition(null);
- }
- beginTransition.invalidate();
- mTransitions.remove(beginTransition);
- }
-
- final Transition endTransition = mediaItem.getEndTransition();
- if (endTransition != null) {
- if (endTransition.getBeforeMediaItem() != null) {
- endTransition.getBeforeMediaItem().setBeginTransition(null);
- }
- endTransition.invalidate();
- mTransitions.remove(endTransition);
- }
-
- mediaItem.setBeginTransition(null);
- mediaItem.setEndTransition(null);
- }
-
- /**
- * Remove the transition before this media item
- *
- * @param index The media item index
- */
- private void removeTransitionBefore(int index) {
- final MediaItem mediaItem = mMediaItems.get(index);
- final Iterator<Transition> it = mTransitions.iterator();
- while (it.hasNext()) {
- Transition t = it.next();
- if (t.getBeforeMediaItem() == mediaItem) {
- mMANativeHelper.setGeneratePreview(true);
- it.remove();
- t.invalidate();
- mediaItem.setBeginTransition(null);
- if (index > 0) {
- mMediaItems.get(index - 1).setEndTransition(null);
- }
- break;
- }
- }
- }
-
- /**
- * Remove the transition after this media item
- *
- * @param mediaItem The media item
- */
- private void removeTransitionAfter(int index) {
- final MediaItem mediaItem = mMediaItems.get(index);
- final Iterator<Transition> it = mTransitions.iterator();
- while (it.hasNext()) {
- Transition t = it.next();
- if (t.getAfterMediaItem() == mediaItem) {
- mMANativeHelper.setGeneratePreview(true);
- it.remove();
- t.invalidate();
- mediaItem.setEndTransition(null);
- /**
- * Invalidate the reference in the next media item
- */
- if (index < mMediaItems.size() - 1) {
- mMediaItems.get(index + 1).setBeginTransition(null);
- }
- break;
- }
- }
- }
-
- /**
- * Compute the duration
- */
- private void computeTimelineDuration() {
- mDurationMs = 0;
- final int mediaItemsCount = mMediaItems.size();
- for (int i = 0; i < mediaItemsCount; i++) {
- final MediaItem mediaItem = mMediaItems.get(i);
- mDurationMs += mediaItem.getTimelineDuration();
- if (mediaItem.getEndTransition() != null) {
- if (i < mediaItemsCount - 1) {
- mDurationMs -= mediaItem.getEndTransition().getDuration();
- }
- }
- }
- }
-
- /*
- * Generate the project thumbnail
- */
- private void generateProjectThumbnail() {
- /*
- * If a thumbnail already exists, then delete it first
- */
- if ((new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).exists()) {
- (new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).delete();
- }
- /*
- * Generate a new thumbnail for the project from first media Item
- */
- if (mMediaItems.size() > 0) {
- MediaItem mI = mMediaItems.get(0);
- /*
- * Keep aspect ratio of the image
- */
- int height = 480;
- int width = mI.getWidth() * height / mI.getHeight();
-
- Bitmap projectBitmap = null;
- String filename = mI.getFilename();
- if (mI instanceof MediaVideoItem) {
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- retriever.setDataSource(filename);
- Bitmap bitmap = retriever.getFrameAtTime();
- retriever.release();
- retriever = null;
- if (bitmap == null) {
- String msg = "Thumbnail extraction from " +
- filename + " failed";
- throw new IllegalArgumentException(msg);
- }
- // Resize the thumbnail to the target size
- projectBitmap =
- Bitmap.createScaledBitmap(bitmap, width, height, true);
- } else {
- try {
- projectBitmap = mI.getThumbnail(width, height, 500);
- } catch (IllegalArgumentException e) {
- String msg = "Project thumbnail extraction from " +
- filename + " failed";
- throw new IllegalArgumentException(msg);
- } catch (IOException e) {
- String msg = "IO Error creating project thumbnail";
- throw new IllegalArgumentException(msg);
- }
- }
-
- FileOutputStream stream = null;
- try {
- stream = new FileOutputStream(mProjectPath + "/" + THUMBNAIL_FILENAME);
- projectBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
- stream.flush();
- } catch (IOException e) {
- throw new IllegalArgumentException ("Error creating project thumbnail");
- } finally {
- IoUtils.closeQuietly(stream);
- projectBitmap.recycle();
- }
- }
- }
-
- /**
- * Clears the preview surface
- *
- * @param surfaceHolder SurfaceHolder where the preview is rendered
- * and needs to be cleared.
- */
- public void clearSurface(SurfaceHolder surfaceHolder) {
- if (surfaceHolder == null) {
- throw new IllegalArgumentException("Invalid surface holder");
- }
-
- final Surface surface = surfaceHolder.getSurface();
- if (surface == null) {
- throw new IllegalArgumentException("Surface could not be retrieved from surface holder");
- }
-
- if (surface.isValid() == false) {
- throw new IllegalStateException("Surface is not valid");
- }
-
- if (mMANativeHelper != null) {
- mMANativeHelper.clearPreviewSurface(surface);
- } else {
- Log.w(TAG, "Native helper was not ready!");
- }
- }
-
- /**
- * Grab the semaphore which arbitrates access to the editor
- *
- * @throws InterruptedException
- */
- private void lock() throws InterruptedException {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbing semaphore", new Throwable());
- }
- mLock.acquire();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbed semaphore");
- }
- }
-
- /**
- * Tries to grab the semaphore with a specified time out which arbitrates access to the editor
- *
- * @param timeoutMs time out in ms.
- *
- * @return true if the semaphore is acquired, false otherwise
- * @throws InterruptedException
- */
- private boolean lock(long timeoutMs) throws InterruptedException {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbing semaphore with timeout " + timeoutMs, new Throwable());
- }
-
- boolean acquireSem = mLock.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "lock: grabbed semaphore status " + acquireSem);
- }
-
- return acquireSem;
- }
-
- /**
- * Release the semaphore which arbitrates access to the editor
- */
- private void unlock() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "unlock: releasing semaphore");
- }
- mLock.release();
- }
-
- /**
- * Dumps the heap memory usage information to file
- */
- private static void dumpHeap (String filename) throws Exception {
- /* Cleanup as much as possible before dump
- */
- System.gc();
- System.runFinalization();
- Thread.sleep(1000);
- String state = Environment.getExternalStorageState();
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- String extDir =
- Environment.getExternalStorageDirectory().toString();
-
- /* If dump file already exists, then delete it first
- */
- if ((new File(extDir + "/" + filename + ".dump")).exists()) {
- (new File(extDir + "/" + filename + ".dump")).delete();
- }
- /* Dump native heap
- */
- FileOutputStream ost =
- new FileOutputStream(extDir + "/" + filename + ".dump");
- Debug.dumpNativeHeap(ost.getFD());
- ost.close();
- }
- }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java
deleted file mode 100644
index 202a2df..0000000
--- a/media/java/android/media/videoeditor/VideoEditorProfile.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-/**
- * The VideoEditorProfile class is used to retrieve the
- * predefined videoeditor profile settings for videoeditor applications.
- * These settings are read-only.
- *
- * <p>The videoeditor profile specifies the following set of parameters:
- * <ul>
- * <li> max input video frame width
- * <li> max input video frame height
- * <li> max output video frame width
- * <li> max output video frame height
- * </ul>
- * {@hide}
- */
-public class VideoEditorProfile
-{
- static {
- System.loadLibrary("media_jni");
- native_init();
- }
- /**
- * The max input video frame width
- */
- public int maxInputVideoFrameWidth;
-
- /**
- * The max input video frame height
- */
- public int maxInputVideoFrameHeight;
-
- /**
- * The max ouput video frame width
- */
- public int maxOutputVideoFrameWidth;
-
- /**
- * The max ouput video frame height
- */
- public int maxOutputVideoFrameHeight;
-
- /**
- * Returns the videoeditor profile
- */
- public static VideoEditorProfile get() {
- return native_get_videoeditor_profile();
- }
-
- /**
- * Returns the supported profile by given video codec
- */
- public static int getExportProfile(int vidCodec) {
- int profile = -1;
-
- switch (vidCodec) {
- case MediaProperties.VCODEC_H263:
- case MediaProperties.VCODEC_H264:
- case MediaProperties.VCODEC_MPEG4:
- profile = native_get_videoeditor_export_profile(vidCodec);
- break;
- default :
- throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
- }
-
- return profile;
- }
-
- /**
- * Returns the supported level by given video codec
- */
- public static int getExportLevel(int vidCodec) {
- int level = -1;
-
- switch (vidCodec) {
- case MediaProperties.VCODEC_H263:
- case MediaProperties.VCODEC_H264:
- case MediaProperties.VCODEC_MPEG4:
- level = native_get_videoeditor_export_level(vidCodec);
- break;
- default :
- throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
- }
-
- return level;
- }
-
- // Private constructor called by JNI
- private VideoEditorProfile(int inputWidth,
- int inputHeight,
- int outputWidth,
- int outputHeight) {
-
- this.maxInputVideoFrameWidth = inputWidth;
- this.maxInputVideoFrameHeight = inputHeight;
- this.maxOutputVideoFrameWidth = outputWidth;
- this.maxOutputVideoFrameHeight = outputHeight;
- }
-
- // Methods implemented by JNI
- private static native final void native_init();
- private static native final VideoEditorProfile
- native_get_videoeditor_profile();
- private static native final int native_get_videoeditor_export_profile(int codec);
- private static native final int native_get_videoeditor_export_level(int level);
-
-}
diff --git a/media/java/android/media/videoeditor/WaveformData.java b/media/java/android/media/videoeditor/WaveformData.java
deleted file mode 100644
index 6c10e3c..0000000
--- a/media/java/android/media/videoeditor/WaveformData.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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 android.media.videoeditor;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-/**
- * Class which describes the waveform data of an audio track. The gain values
- * represent the average gain for an audio frame. For audio codecs which do not
- * operate on a per frame bases (eg. ALAW, ULAW) a reasonable audio frame
- * duration will be assumed (eg. 50ms).
- * {@hide}
- */
-public class WaveformData {
- /*
- * Instance variables
- */
- private final int mFrameDurationMs;
- private final int mFramesCount;
- private final short[] mGains;
-
- /*
- * This constructor shall not be used
- */
- @SuppressWarnings("unused")
- private WaveformData() throws IOException {
- mFrameDurationMs = 0;
- mFramesCount = 0;
- mGains = null;
- }
-
- /*
- * Constructor
- *
- * @param audioWaveformFilename The name of the audio waveform file
- *
- * The file format is as following:
- * <ul>
- * <li>first 4 bytes provide the number of samples for each value, as
- * big-endian signed</li>
- * <li>4 following bytes is the total number of values in the file, as
- * big-endian signed</li>
- * <li>then, all values follow as bytes</li>
- * </ul>
- *
- * @throws IOException on failure of file input stream operations
- * @throws IllegalArgumentException if audioWaveformFilename is null
- */
- WaveformData(String audioWaveformFilename) throws IOException {
-
- if (audioWaveformFilename == null) {
- throw new IllegalArgumentException("WaveformData : filename is null");
- }
-
- FileInputStream audioGraphFileReadHandle = null;
-
- try {
- final File audioGraphFileContext = new File(audioWaveformFilename);
-
- audioGraphFileReadHandle = new FileInputStream(audioGraphFileContext);
- /*
- * Read frame duration
- */
- final byte tempFrameDuration[] = new byte[4];
-
- audioGraphFileReadHandle.read(tempFrameDuration, 0, 4);
-
- int tempFrameDurationMs = 0;
- int tempFramesCounter = 0;
- for (int i = 0; i < 4; i++) {
- tempFrameDurationMs = (tempFrameDurationMs << 8);
- tempFrameDurationMs = (tempFrameDurationMs | (tempFrameDuration[i] & 0xff));
- }
- mFrameDurationMs = tempFrameDurationMs;
-
- /*
- * Read count
- */
- final byte tempFramesCount[] = new byte[4];
-
- audioGraphFileReadHandle.read(tempFramesCount, 0, 4);
- for (int i = 0; i < 4; i++) {
- tempFramesCounter = (tempFramesCounter << 8);
- tempFramesCounter = (tempFramesCounter | (tempFramesCount[i] & 0xff));
- }
- mFramesCount = tempFramesCounter;
-
- /*
- * Capture the graph values
- */
- mGains = new short[mFramesCount];
-
- for (int i = 0; i < mFramesCount; i++) {
- mGains[i] = (short)audioGraphFileReadHandle.read();
- }
- } finally {
- if (audioGraphFileReadHandle != null) {
- audioGraphFileReadHandle.close();
- }
- }
- }
-
- /**
- * @return The duration of a frame in milliseconds
- */
- public int getFrameDuration() {
- return mFrameDurationMs;
- }
-
- /**
- * @return The number of frames within the waveform data
- */
- public int getFramesCount() {
- return mFramesCount;
- }
-
- /**
- * @return The array of frame gains. The size of the array is the frames
- * count. The values of the frame gains range from 0 to 255.
- */
- public short[] getFrameGains() {
- return mGains;
- }
-}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 7c45682..4fbd2a4 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -297,8 +297,6 @@
}
JDrm::~JDrm() {
- mDrm.clear();
-
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObject);
@@ -363,6 +361,13 @@
}
}
+void JDrm::disconnect() {
+ if (mDrm != NULL) {
+ mDrm->destroyPlugin();
+ mDrm.clear();
+ }
+}
+
// static
bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
@@ -527,6 +532,7 @@
sp<JDrm> drm = setDrm(env, thiz, NULL);
if (drm != NULL) {
drm->setListener(NULL);
+ drm->disconnect();
}
}
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 620ad28..b7b8e5d 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -47,6 +47,8 @@
void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
status_t setListener(const sp<DrmListener>& listener);
+ void disconnect();
+
protected:
virtual ~JDrm();
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index 48a9132..1e5c700 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -290,75 +290,6 @@
}
return static_cast<jint>(levels[index]);
}
-static jobject
-android_media_MediaProfiles_native_get_videoeditor_profile(JNIEnv *env, jobject thiz)
-{
- ALOGV("native_get_videoeditor_profile");
-
- int maxInputFrameWidth =
- sProfiles->getVideoEditorCapParamByName("videoeditor.input.width.max");
- int maxInputFrameHeight =
- sProfiles->getVideoEditorCapParamByName("videoeditor.input.height.max");
- int maxOutputFrameWidth =
- sProfiles->getVideoEditorCapParamByName("videoeditor.output.width.max");
- int maxOutputFrameHeight =
- sProfiles->getVideoEditorCapParamByName("videoeditor.output.height.max");
-
- // Check on the values retrieved
- if (maxInputFrameWidth == -1 || maxInputFrameHeight == -1 ||
- maxOutputFrameWidth == -1 || maxOutputFrameHeight == -1) {
-
- jniThrowException(env, "java/lang/RuntimeException",\
- "Error retrieving videoeditor profile params");
- return NULL;
- }
- ALOGV("native_get_videoeditor_profile \
- inWidth:%d inHeight:%d,outWidth:%d, outHeight:%d",\
- maxInputFrameWidth,maxInputFrameHeight,\
- maxOutputFrameWidth,maxOutputFrameHeight);
-
- jclass VideoEditorProfileClazz =
- env->FindClass("android/media/videoeditor/VideoEditorProfile");
- jmethodID VideoEditorProfileConstructorMethodID =
- env->GetMethodID(VideoEditorProfileClazz, "<init>", "(IIII)V");
- return env->NewObject(VideoEditorProfileClazz,
- VideoEditorProfileConstructorMethodID,
- maxInputFrameWidth,
- maxInputFrameHeight,
- maxOutputFrameWidth,
- maxOutputFrameHeight);
-}
-static jint
-android_media_MediaProfiles_native_get_videoeditor_export_profile(
- JNIEnv *env, jobject thiz, jint codec)
-{
- ALOGV("android_media_MediaProfiles_native_get_export_profile index ");
- int profile =0;
- profile = sProfiles->getVideoEditorExportParamByName("videoeditor.export.profile", codec);
- // Check the values retrieved
- if (profile == -1) {
- jniThrowException(env, "java/lang/RuntimeException",\
- "Error retrieving videoeditor export profile params");
- return -1;
- }
- return static_cast<jint>(profile);
-}
-
-static jint
-android_media_MediaProfiles_native_get_videoeditor_export_level(
- JNIEnv *env, jobject thiz, jint codec)
-{
- ALOGV("android_media_MediaProfiles_native_get_export_level");
- int level =0;
- level = sProfiles->getVideoEditorExportParamByName("videoeditor.export.level", codec);
- // Check the values retrieved
- if (level == -1) {
- jniThrowException(env, "java/lang/RuntimeException",\
- "Error retrieving videoeditor export level params");
- return -1;
- }
- return static_cast<jint>(level);
-}
static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
{"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
{"native_get_num_file_formats", "()I", (void *)android_media_MediaProfiles_native_get_num_file_formats},
@@ -396,19 +327,10 @@
{"native_get_image_encoding_quality_level","(II)I", (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
};
-static JNINativeMethod gMethodsForVideoEditorProfileClass[] = {
- {"native_init", "()V", (void *)android_media_MediaProfiles_native_init},
- {"native_get_videoeditor_profile", "()Landroid/media/videoeditor/VideoEditorProfile;", (void *)android_media_MediaProfiles_native_get_videoeditor_profile},
- {"native_get_videoeditor_export_profile", "(I)I", (void *)android_media_MediaProfiles_native_get_videoeditor_export_profile},
- {"native_get_videoeditor_export_level", "(I)I", (void *)android_media_MediaProfiles_native_get_videoeditor_export_level},
-};
-
static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities";
static const char* const kDecoderCapabilitiesClassPathName = "android/media/DecoderCapabilities";
static const char* const kCamcorderProfileClassPathName = "android/media/CamcorderProfile";
static const char* const kCameraProfileClassPathName = "android/media/CameraProfile";
-static const char* const kVideoEditorProfileClassPathName =
- "android/media/videoeditor/VideoEditorProfile";
// This function only registers the native methods, and is called from
// JNI_OnLoad in android_media_MediaPlayer.cpp
@@ -434,11 +356,6 @@
gMethodsForCameraProfileClass,
NELEM(gMethodsForCameraProfileClass));
- int ret5 = AndroidRuntime::registerNativeMethods(env,
- kVideoEditorProfileClassPathName,
- gMethodsForVideoEditorProfileClass,
- NELEM(gMethodsForVideoEditorProfileClass));
-
// Success if all return values from above are 0
- return (ret1 || ret2 || ret3 || ret4 || ret5);
+ return (ret1 || ret2 || ret3 || ret4);
}
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 0e55228..d781336 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -859,6 +859,7 @@
result = malloc(exifdata->size);
if (result) {
memcpy(result, exifdata->data, exifdata->size);
+ outThumbSize = exifdata->size;
}
}
exif_data_unref(exifdata);
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
deleted file mode 100644
index 312c366..0000000
--- a/media/jni/mediaeditor/Android.mk
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- VideoEditorMain.cpp \
- VideoEditorClasses.cpp \
- VideoEditorOsal.cpp \
- VideoEditorJava.cpp \
- VideoEditorPropertiesMain.cpp \
- VideoEditorThumbnailMain.cpp \
- VideoBrowserMain.c
-
-LOCAL_C_INCLUDES += \
- $(TOP)/frameworks/base/core/jni \
- $(TOP)/frameworks/base/include \
- $(TOP)/frameworks/base/include/media \
- $(TOP)/frameworks/base/media/libmediaplayerservice \
- $(TOP)/frameworks/base/media/libstagefright \
- $(TOP)/frameworks/base/media/libstagefright/include \
- $(TOP)/frameworks/base/media/libstagefright/rtsp \
- $(JNI_H_INCLUDE) \
- $(TOP)/frameworks/native/include/media/editor \
- $(TOP)/frameworks/base/core/jni/mediaeditor \
- $(TOP)/frameworks/av/libvideoeditor/vss/inc \
- $(TOP)/frameworks/av/libvideoeditor/vss/common/inc \
- $(TOP)/frameworks/av/libvideoeditor/vss/mcs/inc \
- $(TOP)/frameworks/av/libvideoeditor/vss/stagefrightshells/inc \
- $(TOP)/frameworks/av/libvideoeditor/lvpp \
- $(TOP)/frameworks/av/libvideoeditor/osal/inc \
- $(TOP)/frameworks/native/include/media/openmax
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid_runtime \
- libaudioutils \
- libbinder \
- libcutils \
- liblog \
- libdl \
- libgui \
- libmedia \
- libnativehelper \
- libstagefright \
- libstagefright_foundation \
- libstagefright_omx \
- libutils \
- libvideoeditor_core \
- libvideoeditor_osal \
- libvideoeditor_videofilters \
- libvideoeditorplayer \
-
-
-LOCAL_CFLAGS += \
- -DUSE_STAGEFRIGHT_CODECS \
- -DUSE_STAGEFRIGHT_AUDIODEC \
- -DUSE_STAGEFRIGHT_VIDEODEC \
- -DUSE_STAGEFRIGHT_AUDIOENC \
- -DUSE_STAGEFRIGHT_VIDEOENC \
- -DUSE_STAGEFRIGHT_READERS \
- -DUSE_STAGEFRIGHT_3GPP_READER
-
-LOCAL_MODULE:= libvideoeditor_jni
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/media/jni/mediaeditor/NOTICE b/media/jni/mediaeditor/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/media/jni/mediaeditor/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/media/jni/mediaeditor/VideoBrowserInternal.h b/media/jni/mediaeditor/VideoBrowserInternal.h
deleted file mode 100644
index f4eaab8..0000000
--- a/media/jni/mediaeditor/VideoBrowserInternal.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-
-#ifndef VIDEO_BROWSER_INTERNAL_H
-#define VIDEO_BROWSER_INTERNAL_H
-
-#include "VideoBrowserMain.h"
-
-#include "M4READER_Common.h"
-#include "M4DECODER_Common.h"
-
-
-#define VIDEO_BROWSER_BGR565
-
-/*---------------------------- MACROS ----------------------------*/
-#define CHECK_PTR(fct, p, err, errValue) \
-{ \
- if (M4OSA_NULL == p) \
- { \
- err = errValue ; \
- M4OSA_TRACE1_1("" #fct "(L%d): " #p " is NULL, returning " #errValue "", __LINE__) ; \
- goto fct##_cleanUp; \
- } \
-}
-
-#define CHECK_ERR(fct, err) \
-{ \
- if (M4OSA_ERR_IS_ERROR(err)) \
- { \
- M4OSA_TRACE1_2("" #fct "(L%d): ERROR 0x%.8x returned", __LINE__,err) ; \
- goto fct##_cleanUp; \
- } \
- else if (M4OSA_ERR_IS_WARNING(err)) \
- { \
- M4OSA_TRACE2_2("" #fct "(L%d): WARNING 0x%.8x returned", __LINE__,err) ; \
- } \
-}
-
-#define CHECK_STATE(fct, state, pC) \
-{ \
- if (state != pC->m_state) \
- { \
- M4OSA_TRACE1_1("" #fct " called in bad state %d", pC->m_state) ; \
- err = M4ERR_STATE ; \
- goto fct##_cleanUp; \
- } \
-}
-
-#define SAFE_FREE(p) \
-{ \
- if (M4OSA_NULL != p) \
- { \
- free(p) ; \
- p = M4OSA_NULL ; \
- } \
-}
-
-/*--- Video Browser state ---*/
-typedef enum
-{
- VideoBrowser_kVBCreating,
- VideoBrowser_kVBOpened,
- VideoBrowser_kVBBrowsing
-} VideoBrowser_videoBrowerState;
-
-
-/*--- Video Browser execution context. ---*/
-typedef struct
-{
- VideoBrowser_videoBrowerState m_state ;
- VideoBrowser_videoBrowerDrawMode m_drawmode;
-
- M4OSA_Context g_hbmp2;
- M4OSA_Context dc;
- M4OSA_Int16* g_bmPixels2;
-
- /*--- Reader parameters ---*/
- M4OSA_FileReadPointer m_fileReadPtr;
- M4READER_GlobalInterface* m_3gpReader ;
- M4READER_DataInterface* m_3gpData ;
- M4READER_MediaType m_mediaType ;
- M4OSA_Context m_pReaderCtx ;
-
- M4_StreamHandler* m_pStreamHandler ;
- M4_AccessUnit m_accessUnit ;
-
- /*--- Decoder parameters ---*/
- M4DECODER_VideoInterface* m_pDecoder ;
- M4OSA_Context m_pDecoderCtx ;
-
- /*--- Common display parameters ---*/
- M4OSA_UInt32 m_x ;
- M4OSA_UInt32 m_y ;
- M4VIFI_ImagePlane m_outputPlane[3] ;
-
- /*--- Current browsing time ---*/
- M4OSA_UInt32 m_currentCTS ;
-
- /*--- Platform dependent display parameters ---*/
- M4OSA_Context m_pCoreContext ;
-
- /*--- Callback function settings ---*/
- videoBrowser_Callback m_pfCallback;
- M4OSA_Void* m_pCallbackUserData;
-
- /*--- Codec Loader core context ---*/
- M4OSA_Context m_pCodecLoaderContext;
-
- /*--- Required color type ---*/
- VideoBrowser_VideoColorType m_frameColorType;
-
-} VideoBrowserContext;
-
-#endif /* VIDEO_BROWSER_INTERNAL_H */
diff --git a/media/jni/mediaeditor/VideoBrowserMain.c b/media/jni/mediaeditor/VideoBrowserMain.c
deleted file mode 100644
index c6c6000..0000000
--- a/media/jni/mediaeditor/VideoBrowserMain.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-#include "VideoEditorVideoDecoder.h"
-#include "VideoEditor3gpReader.h"
-
-#include <utils/Log.h>
-#include "VideoBrowserInternal.h"
-#include "LVOSA_FileReader_optim.h"
-
-//#define M4OSA_TRACE_LEVEL 1
-#if (M4OSA_TRACE_LEVEL >= 1)
-#undef M4OSA_TRACE1_0
-#undef M4OSA_TRACE1_1
-#undef M4OSA_TRACE1_2
-#undef M4OSA_TRACE1_3
-
-#define M4OSA_TRACE1_0(a) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a);
-#define M4OSA_TRACE1_1(a,b) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b);
-#define M4OSA_TRACE1_2(a,b,c) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c);
-#define M4OSA_TRACE1_3(a,b,c,d) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c,d);
-#endif
-
-/******************************************************************************
- * M4OSA_ERR videoBrowserSetWindow(
- * M4OSA_Context pContext, M4OSA_UInt32 x,
- * M4OSA_UInt32 y, M4OSA_UInt32 dx, M4OSA_UInt32 dy);
- * @brief This function sets the size and the position of the display.
- * @param pContext (IN) : Video Browser context
- * @param pPixelArray (IN) : Array to hold the video frame.
- * @param x (IN) : Horizontal position of the top left
- * corner
- * @param y (IN) : Vertical position of the top left corner
- * @param dx (IN) : Width of the display window
- * @param dy (IN) : Height of the video window
- * @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
- ******************************************************************************/
-M4OSA_ERR videoBrowserSetWindow(
- M4OSA_Context pContext,
- M4OSA_Int32 *pPixelArray,
- M4OSA_UInt32 x, M4OSA_UInt32 y,
- M4OSA_UInt32 dx, M4OSA_UInt32 dy)
-{
- VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
- M4OSA_ERR err = M4NO_ERROR;
-
- M4OSA_TRACE2_5("videoBrowserSetWindow: entering with 0x%x %d %d %d %d ",
- pContext, x, y, dx, dy);
-
- /*--- Sanity checks ---*/
- CHECK_PTR(videoBrowserSetWindow, pContext, err, M4ERR_PARAMETER);
- CHECK_PTR(videoBrowserSetWindow, pPixelArray, err, M4ERR_PARAMETER);
- CHECK_STATE(videoBrowserSetWindow, VideoBrowser_kVBOpened, pC);
-
- pC->m_outputPlane[0].u_topleft = 0;
-
- pC->m_outputPlane[0].u_height = dy;
- pC->m_outputPlane[0].u_width = dx;
- pC->m_x = x;
- pC->m_y = y;
-
- if (pC->m_frameColorType == VideoBrowser_kGB565) {
- pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width << 1;
- pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
- pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height,
- VIDEOBROWSER, (M4OSA_Char *)"output plane");
-
- CHECK_PTR(videoBrowserSetWindow,
- pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
- }
- else if (pC->m_frameColorType == VideoBrowser_kYUV420) {
- pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width;
- pC->m_outputPlane[1].u_height = pC->m_outputPlane[0].u_height >> 1;
- pC->m_outputPlane[1].u_width = pC->m_outputPlane[0].u_width >> 1;
- pC->m_outputPlane[1].u_topleft = 0;
- pC->m_outputPlane[1].u_stride = pC->m_outputPlane[1].u_width;
-
- pC->m_outputPlane[2].u_height = pC->m_outputPlane[0].u_height >> 1;
- pC->m_outputPlane[2].u_width = pC->m_outputPlane[0].u_width >> 1;
- pC->m_outputPlane[2].u_topleft = 0;
- pC->m_outputPlane[2].u_stride = pC->m_outputPlane[2].u_width;
-
- pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)pPixelArray;
-
- CHECK_PTR(videoBrowserSetWindow,
- pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
-
- pC->m_outputPlane[1].pac_data =
- pC->m_outputPlane[0].pac_data +
- (pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height);
-
- pC->m_outputPlane[2].pac_data =
- pC->m_outputPlane[1].pac_data +
- (pC->m_outputPlane[1].u_stride * pC->m_outputPlane[1].u_height);
- }
-
-
- M4OSA_TRACE2_0("videoBrowserSetWindow returned NO ERROR");
- return M4NO_ERROR;
-
-videoBrowserSetWindow_cleanUp:
-
- M4OSA_TRACE2_1("videoBrowserSetWindow returned 0x%x", err);
- return err;
-}
-
-/******************************************************************************
-* @brief This function allocates the resources needed for browsing a video file
-* @param ppContext (OUT): Pointer on a context filled by this function.
-* @param pURL (IN) : Path of File to browse
-* @param DrawMode (IN) : Indicate which method is used to draw (Direct draw etc...)
-* @param pfCallback (IN) : Callback function to be called when a frame must be displayed
-* @param pCallbackData (IN) : User defined data that will be passed as parameter of the callback
-* @param clrType (IN) : Required color type.
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserCreate(
- M4OSA_Context* ppContext,
- M4OSA_Char* pURL,
- M4OSA_UInt32 DrawMode,
- M4OSA_FileReadPointer* ptrF,
- videoBrowser_Callback pfCallback,
- M4OSA_Void* pCallbackData,
- VideoBrowser_VideoColorType clrType)
-{
- VideoBrowserContext* pContext = M4OSA_NULL;
- M4READER_MediaFamily mediaFamily = M4READER_kMediaFamilyUnknown;
- M4_StreamHandler* pStreamHandler = M4OSA_NULL;
- M4_VideoStreamHandler* pVideoStreamHandler = M4OSA_NULL;
- M4DECODER_VideoType decoderType;
- M4DECODER_OutputFilter FilterOption;
-
- M4OSA_Bool deb = M4OSA_TRUE;
- M4OSA_ERR err = M4NO_ERROR;
-
- M4OSA_TRACE1_2(
- "videoBrowserCreate: entering with 0x%x 0x%x", ppContext, pURL);
-
- /*--- Sanity checks ---*/
- CHECK_PTR(videoBrowserCreate, ppContext, err, M4ERR_PARAMETER);
- *ppContext = M4OSA_NULL ;
- CHECK_PTR(videoBrowserCreate, pURL, err, M4ERR_PARAMETER);
-
- /*--- Create context ---*/
- pContext = (VideoBrowserContext*)M4OSA_32bitAlignedMalloc(
- sizeof(VideoBrowserContext),
- VIDEOBROWSER, (M4OSA_Char*)"Video browser context");
-
- CHECK_PTR(videoBrowserCreate, pContext,err, M4ERR_ALLOC);
- memset((void *)pContext, 0,sizeof(VideoBrowserContext));
-
- /*--- Initialize the context parameters ---*/
- pContext->m_state = VideoBrowser_kVBCreating ;
- pContext->m_frameColorType = clrType;
-
- /*--- Copy the file reader functions ---*/
- memcpy((void *)&pContext->m_fileReadPtr,
- (void *)ptrF,
- sizeof(M4OSA_FileReadPointer)) ;
-
- /* PR#SP00013 DGR bug 13 : first frame is not visible */
- pContext->m_drawmode = DrawMode;
-
-
- /* Retrieve the 3gp reader interface */
- VideoEditor3gpReader_getInterface(&pContext->m_mediaType,
- &pContext->m_3gpReader, &pContext->m_3gpData);
-
- CHECK_PTR(videoBrowserCreate, pContext->m_3gpReader, err, M4ERR_ALLOC);
- CHECK_PTR(videoBrowserCreate, pContext->m_3gpData, err, M4ERR_ALLOC);
-
- /*--- Create the file reader ---*/
- err = pContext->m_3gpReader->m_pFctCreate(&pContext->m_pReaderCtx);
- CHECK_ERR(videoBrowserCreate, err);
- CHECK_PTR(videoBrowserCreate, pContext->m_pReaderCtx, err, M4ERR_ALLOC);
- pContext->m_3gpData->m_readerContext = pContext->m_pReaderCtx;
-
- /*--- Set the OSAL file reader functions ---*/
- err = pContext->m_3gpReader->m_pFctSetOption(
- pContext->m_pReaderCtx,
- M4READER_kOptionID_SetOsaFileReaderFctsPtr,
- (M4OSA_DataOption)(&pContext->m_fileReadPtr));
-
- CHECK_ERR(videoBrowserCreate, err) ;
-
- /*--- Open the file ---*/
- err = pContext->m_3gpReader->m_pFctOpen(pContext->m_pReaderCtx, pURL);
- CHECK_ERR(videoBrowserCreate, err) ;
-
- /*--- Try to find a video stream ---*/
- while (err == M4NO_ERROR)
- {
- err = pContext->m_3gpReader->m_pFctGetNextStream(
- pContext->m_pReaderCtx, &mediaFamily, &pStreamHandler);
-
- /*in case we found a bifs stream or something else...*/
- if ((err == (M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE) ||
- (err == (M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS))
- {
- err = M4NO_ERROR;
- continue;
- }
-
- if (err != M4WAR_NO_MORE_STREAM)
- {
- if (M4READER_kMediaFamilyVideo != mediaFamily)
- {
- err = M4NO_ERROR;
- continue;
- }
-
- pContext->m_pStreamHandler = pStreamHandler;
-
- err = pContext->m_3gpReader->m_pFctReset(
- pContext->m_pReaderCtx, pContext->m_pStreamHandler);
-
- CHECK_ERR(videoBrowserCreate, err);
-
- err = pContext->m_3gpReader->m_pFctFillAuStruct(
- pContext->m_pReaderCtx,
- pContext->m_pStreamHandler,
- &pContext->m_accessUnit);
-
- CHECK_ERR(videoBrowserCreate, err);
-
- pVideoStreamHandler =
- (M4_VideoStreamHandler*)pContext->m_pStreamHandler;
-
- switch (pContext->m_pStreamHandler->m_streamType)
- {
- case M4DA_StreamTypeVideoMpeg4:
- case M4DA_StreamTypeVideoH263:
- {
- pContext->m_pCodecLoaderContext = M4OSA_NULL;
- decoderType = M4DECODER_kVideoTypeMPEG4;
-
-#ifdef USE_SOFTWARE_DECODER
- err = VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
- &decoderType, &pContext->m_pDecoder);
-#else
- err = VideoEditorVideoDecoder_getInterface_MPEG4(
- &decoderType, (void **)&pContext->m_pDecoder);
-#endif
- CHECK_ERR(videoBrowserCreate, err) ;
-
- err = pContext->m_pDecoder->m_pFctCreate(
- &pContext->m_pDecoderCtx,
- pContext->m_pStreamHandler,
- pContext->m_3gpReader,
- pContext->m_3gpData,
- &pContext->m_accessUnit,
- pContext->m_pCodecLoaderContext) ;
-
- CHECK_ERR(videoBrowserCreate, err) ;
- }
- break;
-
- case M4DA_StreamTypeVideoMpeg4Avc:
- {
- pContext->m_pCodecLoaderContext = M4OSA_NULL;
-
- decoderType = M4DECODER_kVideoTypeAVC;
-
-#ifdef USE_SOFTWARE_DECODER
- err = VideoEditorVideoDecoder_getSoftwareInterface_H264(
- &decoderType, &pContext->m_pDecoder);
-#else
- err = VideoEditorVideoDecoder_getInterface_H264(
- &decoderType, (void **)&pContext->m_pDecoder);
-#endif
- CHECK_ERR(videoBrowserCreate, err) ;
-
- err = pContext->m_pDecoder->m_pFctCreate(
- &pContext->m_pDecoderCtx,
- pContext->m_pStreamHandler,
- pContext->m_3gpReader,
- pContext->m_3gpData,
- &pContext->m_accessUnit,
- pContext->m_pCodecLoaderContext) ;
-
- CHECK_ERR(videoBrowserCreate, err) ;
- }
- break;
-
- default:
- err = M4ERR_VB_MEDIATYPE_NOT_SUPPORTED;
- goto videoBrowserCreate_cleanUp;
- }
- }
- }
-
- if (err == M4WAR_NO_MORE_STREAM)
- {
- err = M4NO_ERROR ;
- }
-
- if (M4OSA_NULL == pContext->m_pStreamHandler)
- {
- err = M4ERR_VB_NO_VIDEO ;
- goto videoBrowserCreate_cleanUp ;
- }
-
- err = pContext->m_pDecoder->m_pFctSetOption(
- pContext->m_pDecoderCtx,
- M4DECODER_kOptionID_DeblockingFilter,
- (M4OSA_DataOption)&deb);
-
- if (err == M4WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED)
- {
- err = M4NO_ERROR;
- }
- CHECK_ERR(videoBrowserCreate, err);
-
- FilterOption.m_pFilterUserData = M4OSA_NULL;
-
-
- if (pContext->m_frameColorType == VideoBrowser_kGB565) {
- FilterOption.m_pFilterFunction =
- (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toBGR565;
- }
- else if (pContext->m_frameColorType == VideoBrowser_kYUV420) {
- FilterOption.m_pFilterFunction =
- (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toYUV420;
- }
- else {
- err = M4ERR_PARAMETER;
- goto videoBrowserCreate_cleanUp;
- }
-
- err = pContext->m_pDecoder->m_pFctSetOption(
- pContext->m_pDecoderCtx,
- M4DECODER_kOptionID_OutputFilter,
- (M4OSA_DataOption)&FilterOption);
-
- CHECK_ERR(videoBrowserCreate, err);
-
- /* store the callback details */
- pContext->m_pfCallback = pfCallback;
- pContext->m_pCallbackUserData = pCallbackData;
- /* store the callback details */
-
- pContext->m_state = VideoBrowser_kVBOpened;
- *ppContext = pContext;
-
- M4OSA_TRACE1_0("videoBrowserCreate returned NO ERROR");
- return M4NO_ERROR;
-
-videoBrowserCreate_cleanUp:
-
- if (M4OSA_NULL != pContext)
- {
- if (M4OSA_NULL != pContext->m_pDecoderCtx)
- {
- pContext->m_pDecoder->m_pFctDestroy(pContext->m_pDecoderCtx);
- pContext->m_pDecoderCtx = M4OSA_NULL;
- }
-
- if (M4OSA_NULL != pContext->m_pReaderCtx)
- {
- pContext->m_3gpReader->m_pFctClose(pContext->m_pReaderCtx);
- pContext->m_3gpReader->m_pFctDestroy(pContext->m_pReaderCtx);
- pContext->m_pReaderCtx = M4OSA_NULL;
- }
- SAFE_FREE(pContext->m_pDecoder);
- SAFE_FREE(pContext->m_3gpReader);
- SAFE_FREE(pContext->m_3gpData);
- SAFE_FREE(pContext);
- }
-
- M4OSA_TRACE2_1("videoBrowserCreate returned 0x%x", err);
- return err;
-}
-
-/******************************************************************************
-* M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext);
-* @brief This function frees the resources needed for browsing a
-* video file.
-* @param pContext (IN) : Video browser context
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE
-******************************************************************************/
-M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext)
-{
- VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
- M4OSA_ERR err = M4NO_ERROR;
-
- M4OSA_TRACE2_1("videoBrowserCleanUp: entering with 0x%x", pContext);
-
- /*--- Sanity checks ---*/
- CHECK_PTR(videoBrowserCleanUp, pContext, err, M4ERR_PARAMETER);
-
- if (M4OSA_NULL != pC->m_pDecoderCtx)
- {
- pC->m_pDecoder->m_pFctDestroy(pC->m_pDecoderCtx);
- pC->m_pDecoderCtx = M4OSA_NULL ;
- }
-
- if (M4OSA_NULL != pC->m_pReaderCtx)
- {
- pC->m_3gpReader->m_pFctClose(pC->m_pReaderCtx) ;
- pC->m_3gpReader->m_pFctDestroy(pC->m_pReaderCtx);
- pC->m_pReaderCtx = M4OSA_NULL;
- }
-
- SAFE_FREE(pC->m_pDecoder);
- SAFE_FREE(pC->m_3gpReader);
- SAFE_FREE(pC->m_3gpData);
-
- if (pC->m_frameColorType != VideoBrowser_kYUV420) {
- SAFE_FREE(pC->m_outputPlane[0].pac_data);
- }
- SAFE_FREE(pC);
-
- M4OSA_TRACE2_0("videoBrowserCleanUp returned NO ERROR");
- return M4NO_ERROR;
-
-videoBrowserCleanUp_cleanUp:
-
- M4OSA_TRACE2_1("videoBrowserCleanUp returned 0x%x", err);
- return err;
-}
-/******************************************************************************
-* M4OSA_ERR videoBrowserPrepareFrame(
-* M4OSA_Context pContext, M4OSA_UInt32* pTime);
-* @brief This function prepares the frame.
-* @param pContext (IN) : Video browser context
-* @param pTime (IN/OUT) : Pointer on the time to reach. Updated
-* by this function with the reached time
-* @param tolerance (IN) : We may decode an earlier frame within the tolerance.
-* The time difference is specified in milliseconds.
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime,
- M4OSA_UInt32 tolerance)
-{
- VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
- M4OSA_ERR err = M4NO_ERROR;
- M4OSA_UInt32 targetTime = 0;
- M4_MediaTime timeMS = 0;
- M4OSA_Bool bJumpNeeded = M4OSA_FALSE;
-
- /*--- Sanity checks ---*/
- CHECK_PTR(videoBrowserPrepareFrame, pContext, err, M4ERR_PARAMETER);
- CHECK_PTR(videoBrowserPrepareFrame, pTime, err, M4ERR_PARAMETER);
-
- targetTime = *pTime ;
-
- /*--- Check the state, if this is the first call to this function
- we move to the state "browsing" ---*/
- if (VideoBrowser_kVBOpened == pC->m_state)
- {
- pC->m_state = VideoBrowser_kVBBrowsing;
- }
- else if (VideoBrowser_kVBBrowsing != pC->m_state)
- {
- err = M4ERR_STATE ;
- goto videoBrowserPrepareFrame_cleanUp;
- }
-
- // If we jump backward or forward to a time greater than current position by
- // 85ms (~ 2 frames), we want to jump.
- if (pC->m_currentCTS == 0 ||
- targetTime < pC->m_currentCTS ||
- targetTime > (pC->m_currentCTS + 85))
- {
- bJumpNeeded = M4OSA_TRUE;
- }
-
- timeMS = (M4_MediaTime)targetTime;
- err = pC->m_pDecoder->m_pFctDecode(
- pC->m_pDecoderCtx, &timeMS, bJumpNeeded, tolerance);
-
- if ((err != M4NO_ERROR) && (err != M4WAR_NO_MORE_AU))
- {
- return err;
- }
-
- err = pC->m_pDecoder->m_pFctRender(
- pC->m_pDecoderCtx, &timeMS, pC->m_outputPlane, M4OSA_TRUE);
-
- if (M4WAR_VIDEORENDERER_NO_NEW_FRAME == err)
- {
- return err;
- }
- CHECK_ERR(videoBrowserPrepareFrame, err) ;
-
- pC->m_currentCTS = (M4OSA_UInt32)timeMS;
-
- *pTime = pC->m_currentCTS;
-
- return M4NO_ERROR;
-
-videoBrowserPrepareFrame_cleanUp:
-
- if ((M4WAR_INVALID_TIME == err) || (M4WAR_NO_MORE_AU == err))
- {
- err = M4NO_ERROR;
- }
- else if (M4OSA_NULL != pC)
- {
- pC->m_currentCTS = 0;
- }
-
- M4OSA_TRACE2_1("videoBrowserPrepareFrame returned 0x%x", err);
- return err;
-}
-
-/******************************************************************************
-* M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext);
-* @brief This function displays the current frame.
-* @param pContext (IN) : Video browser context
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext)
-{
- VideoBrowserContext* pC = (VideoBrowserContext*)pContext ;
- M4OSA_ERR err = M4NO_ERROR ;
-
- /*--- Sanity checks ---*/
- CHECK_PTR(videoBrowserDisplayCurrentFrame, pContext, err, M4ERR_PARAMETER);
-
- // Request display of the frame
- pC->m_pfCallback((M4OSA_Context) pC, // VB context
- VIDEOBROWSER_DISPLAY_FRAME, // action requested
- M4NO_ERROR, // error code
- (M4OSA_Void*) &(pC->m_outputPlane[0]), // image to be displayed
- (M4OSA_Void*) pC->m_pCallbackUserData); // user-provided data
-
-#ifdef DUMPTOFILE
- {
- M4OSA_Context fileContext;
- M4OSA_Char* fileName = "/sdcard/textBuffer_RGB565.rgb";
- M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,
- M4OSA_kFileWrite | M4OSA_kFileCreate);
-
- M4OSA_fileWriteData(fileContext,
- (M4OSA_MemAddr8) pC->m_outputPlane[0].pac_data,
- pC->m_outputPlane[0].u_height*pC->m_outputPlane[0].u_width*2);
-
- M4OSA_fileWriteClose(fileContext);
- }
-#endif
-
- M4OSA_TRACE2_0("videoBrowserDisplayCurrentFrame returned NO ERROR") ;
- return M4NO_ERROR;
-
-videoBrowserDisplayCurrentFrame_cleanUp:
-
- M4OSA_TRACE2_1("videoBrowserDisplayCurrentFrame returned 0x%x", err) ;
- return err;
-}
diff --git a/media/jni/mediaeditor/VideoBrowserMain.h b/media/jni/mediaeditor/VideoBrowserMain.h
deleted file mode 100644
index 00b5e05..0000000
--- a/media/jni/mediaeditor/VideoBrowserMain.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-
-#ifndef VIDEO_BROWSER_MAIN_H
-#define VIDEO_BROWSER_MAIN_H
-
-/**
- ************************************************************************
- * @file VideoBrowserMain.h
- * @brief Video browser Interface functions
- ************************************************************************
-*/
-
-#define VIDEOBROWSER 0x423
-
-#include "M4OSA_Memory.h"
-#include "M4OSA_CharStar.h"
-#include "M4OSA_OptionID.h"
-#include "M4OSA_Debug.h"
-#include "M4VIFI_FiltersAPI.h"
-#include "M4OSA_FileReader.h"
-
-
-/**
- ************************************************************************
- * @brief Error codes definition.
- * @note These value are the Browser engine specific error codes.
- ************************************************************************
-*/
-#define M4ERR_VB_MEDIATYPE_NOT_SUPPORTED M4OSA_ERR_CREATE(M4_ERR, VIDEOBROWSER, 0x01)
-#define M4ERR_VB_NO_VIDEO M4OSA_ERR_CREATE(M4_ERR, VIDEOBROWSER, 0x02)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Video Browser draw mode, extension for angle based bliting can be done
- */
-typedef enum
-{
- VideoBrowser_kVBNormalBliting
-} VideoBrowser_videoBrowerDrawMode;
-
-
-/*--- Video Browser output frame color type ---*/
-typedef enum
-{
- VideoBrowser_kYUV420,
- VideoBrowser_kGB565
-} VideoBrowser_VideoColorType;
-
-/**
- ************************************************************************
- * enumeration VideoBrowser_Notification
- * @brief Video Browser notification type.
- * @note This callback mechanism must be used to wait the completion of an asynchronous
- * operation, before calling another API function.
- ************************************************************************
-*/
-typedef enum
-{
- /**
- * A frame is ready to be displayed, it should be displayed in the callback function
- * pCbData type = M4VIFI_ImagePlane*
- */
- VIDEOBROWSER_DISPLAY_FRAME = 0x00000001,
- VIDEOBROWSER_NOTIFICATION_NONE = 0xffffffff
-}VideoBrowser_Notification;
-
-
-/**
- ************************************************************************
- * @brief videoBrowser_Callback type definition
- * @param pInstance (IN) Video Browser context.
- * @param notificationID (IN) Id of the callback which generated the error
- * @param errCode (IN) Error code from the core
- * @param pCbData (IN) pointer to data associated wit the callback.
- * @param pCbUserData (IN) pointer to application user data passed in init.
- * @note This callback mechanism is used to request display of an image
- ************************************************************************
-*/
-typedef M4OSA_Void (*videoBrowser_Callback) (M4OSA_Context pInstance,
- VideoBrowser_Notification notificationID,
- M4OSA_ERR errCode,
- M4OSA_Void* pCbData,
- M4OSA_Void* pCallbackUserData);
-
-
-/******************************************************************************
-* @brief This function allocates the resources needed for browsing a video file.
-* @param ppContext (OUT): Pointer on a context filled by this function.
-* @param pURL (IN) : Path of File to browse
-* @param DrawMode (IN) : Indicate which method is used to draw (Direct draw etc...)
-* @param pfCallback (IN) : Callback function to be called when a frame must be displayed
-* @param pCallbackData (IN) : User defined data that will be passed as parameter of the callback
-* @param clrType (IN) : Required color type.
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserCreate(M4OSA_Context* ppContext, M4OSA_Char* pURL,
- M4OSA_UInt32 DrawMode,
- M4OSA_FileReadPointer* ptrF,
- videoBrowser_Callback pfCallback,
- M4OSA_Void* pCallbackData,
- VideoBrowser_VideoColorType clrType);
-
-/******************************************************************************
-* @brief This function frees the resources needed for browsing a video file.
-* @param pContext (IN) : Video browser context
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE
-******************************************************************************/
-M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext) ;
-
-
-/******************************************************************************
-* @brief This function allocates the resources needed for browsing a video file.
-* @param pContext (IN) : Video browser context
-* @param pTime (IN/OUT) : Pointer on the time to reach. Updated by
-* this function with the reached time
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime,
- M4OSA_UInt32 tolerance);
-
-/******************************************************************************
-* @brief This function sets the size and the position of the display.
-* @param pContext (IN) : Video Browser context
-* @param pixelArray (IN) : Array to hold the video frame.
-* @param x (IN) : Horizontal position of the top left corner
-* @param y (IN) : Vertical position of the top left corner
-* @param dx (IN) : Width of the display window
-* @param dy (IN) : Height of the video window
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserSetWindow(M4OSA_Context pContext, M4OSA_Int32* pixelArray,
- M4OSA_UInt32 x, M4OSA_UInt32 y,
- M4OSA_UInt32 dx, M4OSA_UInt32 dy);
-
-/******************************************************************************
-* @brief This function displays the current frame.
-* @param pContext (IN) : Video browser context
-* @return M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* VIDEO_BROWSER_MAIN_H */
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
deleted file mode 100644
index d29fad3..0000000
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ /dev/null
@@ -1,3146 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorClasses"
-
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Debug.h>
-#include <M4OSA_Thread.h>
-#include <M4VSS3GPP_API.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4DECODER_Common.h>
-};
-
-#define VIDEOEDIT_PROP_JAVA_RESULT_STRING_MAX (128)
-
-#define VIDEOEDIT_JAVA__RESULT_STRING_MAX (128)
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioEffect)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NONE", M4VSS3GPP_kAudioEffectType_None),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_IN", M4VSS3GPP_kAudioEffectType_FadeIn),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_OUT", M4VSS3GPP_kAudioEffectType_FadeOut)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioEffect, AUDIO_EFFECT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioFormat)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NO_AUDIO", M4VIDEOEDITING_kNoneAudio),
- VIDEOEDIT_JAVA_CONSTANT_INIT("AMR_NB", M4VIDEOEDITING_kAMR_NB),
- VIDEOEDIT_JAVA_CONSTANT_INIT("AAC", M4VIDEOEDITING_kAAC),
- VIDEOEDIT_JAVA_CONSTANT_INIT("AAC_PLUS", M4VIDEOEDITING_kAACplus),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ENHANCED_AAC_PLUS", M4VIDEOEDITING_keAACplus),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MP3", M4VIDEOEDITING_kMP3),
- VIDEOEDIT_JAVA_CONSTANT_INIT("EVRC", M4VIDEOEDITING_kEVRC),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PCM", M4VIDEOEDITING_kPCM),
- VIDEOEDIT_JAVA_CONSTANT_INIT("NULL_AUDIO", M4VIDEOEDITING_kNullAudio),
- VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED_AUDIO", M4VIDEOEDITING_kUnsupportedAudio)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioFormat, AUDIO_FORMAT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioSamplingFrequency)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_DEFAULT", M4VIDEOEDITING_kDefault_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_8000", M4VIDEOEDITING_k8000_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_16000", M4VIDEOEDITING_k16000_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_22050", M4VIDEOEDITING_k22050_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_24000", M4VIDEOEDITING_k24000_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_32000", M4VIDEOEDITING_k32000_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_44100", M4VIDEOEDITING_k44100_ASF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_48000", M4VIDEOEDITING_k48000_ASF)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioSamplingFrequency,AUDIO_SAMPLING_FREQUENCY_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioTransition)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NONE", M4VSS3GPP_kAudioTransitionType_None),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CROSS_FADE", M4VSS3GPP_kAudioTransitionType_CrossFade)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioTransition, AUDIO_TRANSITION_CLASS_NAME, M4OSA_NULL,
- M4OSA_NULL)
-
-
-static const char*
-videoEditClasses_getUnknownBitrateString(int bitrate)
-{
- static char string[VIDEOEDIT_JAVA__RESULT_STRING_MAX] = "";
-
- M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1, (M4OSA_Char*)"%d", bitrate);
-
- // Return the bitrate string.
- return(string);
-}
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Bitrate)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("VARIABLE", M4VIDEOEDITING_kVARIABLE_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("UNDEFINED", M4VIDEOEDITING_kUndefinedBitrate),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_9_2_KBPS", M4VIDEOEDITING_k9_2_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_12_2_KBPS", M4VIDEOEDITING_k12_2_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_16_KBPS", M4VIDEOEDITING_k16_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_24_KBPS", M4VIDEOEDITING_k24_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_32_KBPS", M4VIDEOEDITING_k32_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_48_KBPS", M4VIDEOEDITING_k48_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_64_KBPS", M4VIDEOEDITING_k64_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_96_KBPS", M4VIDEOEDITING_k96_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_128_KBPS", M4VIDEOEDITING_k128_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_192_KBPS", M4VIDEOEDITING_k192_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_256_KBPS", M4VIDEOEDITING_k256_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_288_KBPS", M4VIDEOEDITING_k288_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_384_KBPS", M4VIDEOEDITING_k384_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_512_KBPS", M4VIDEOEDITING_k512_KBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_800_KBPS", M4VIDEOEDITING_k800_KBPS),
-/*+ New Encoder bitrates */
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_2_MBPS", M4VIDEOEDITING_k2_MBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_5_MBPS", M4VIDEOEDITING_k5_MBPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BR_8_MBPS", M4VIDEOEDITING_k8_MBPS)
-/*- New Encoder bitrates */
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Bitrate, BITRATE_CLASS_NAME,
- videoEditClasses_getUnknownBitrateString, videoEditClasses_getUnknownBitrateString)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(ClipType)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("THREE_GPP", M4VIDEOEDITING_kFileType_3GPP),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MP4", M4VIDEOEDITING_kFileType_MP4),
- VIDEOEDIT_JAVA_CONSTANT_INIT("AMR", M4VIDEOEDITING_kFileType_AMR),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MP3", M4VIDEOEDITING_kFileType_MP3),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PCM", M4VIDEOEDITING_kFileType_PCM),
- VIDEOEDIT_JAVA_CONSTANT_INIT("JPG", M4VIDEOEDITING_kFileType_JPG),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PNG", M4VIDEOEDITING_kFileType_PNG),
- VIDEOEDIT_JAVA_CONSTANT_INIT("M4V", M4VIDEOEDITING_kFileType_M4V),
- VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kFileType_Unsupported)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(ClipType, FILE_TYPE_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Engine)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("TASK_LOADING_SETTINGS", TASK_LOADING_SETTINGS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("TASK_ENCODING", TASK_ENCODING)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME, M4OSA_NULL,
- M4OSA_NULL)
-
-
-static const char*
-videoEditClasses_getUnknownErrorName(int error)
-{
- static char string[VIDEOEDIT_JAVA__RESULT_STRING_MAX] = "ERR_INTERNAL";
-
- // Format the unknown error string.
- M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1, (M4OSA_Char*)"ERR_INTERNAL(%s)",
- videoEditOsal_getResultString(error));
-
- // Return the error string.
- return(string);
-}
-
-static const char*
-videoEditClasses_getUnknownErrorString(int error)
-{
- // Return the result string.
- return(videoEditOsal_getResultString(error));
-}
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Error)
-{
- // M4OSA_Clock.h
- VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_TIMESCALE_TOO_BIG", \
- M4WAR_TIMESCALE_TOO_BIG ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_CLOCK_BAD_REF_YEAR", \
- M4ERR_CLOCK_BAD_REF_YEAR ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FILE_NOT_FOUND", \
- M4ERR_FILE_NOT_FOUND ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_TRANSCODING_NECESSARY", \
- M4VSS3GPP_WAR_TRANSCODING_NECESSARY ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_MAX_OUTPUT_SIZE_EXCEEDED", \
- M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BUFFER_OUT_TOO_SMALL", \
- M4xVSSWAR_BUFFER_OUT_TOO_SMALL ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NOMORE_SPACE_FOR_FILE", \
- M4xVSSERR_NO_MORE_SPACE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_FILE_TYPE", \
- M4VSS3GPP_ERR_INVALID_FILE_TYPE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_EFFECT_KIND", \
- M4VSS3GPP_ERR_INVALID_EFFECT_KIND ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_EFFECT_TYPE", \
- M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_AUDIO_EFFECT_TYPE", \
- M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_TRANSITION_TYPE", \
- M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_AUDIO_TRANSITION_TYPE", \
- M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_ENCODING_FRAME_RATE", \
- M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EXTERNAL_EFFECT_NULL", \
- M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EXTERNAL_TRANSITION_NULL", \
- M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BEGIN_CUT_LARGER_THAN_DURATION", \
- M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BEGIN_CUT_LARGER_THAN_END_CUT", \
- M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_OVERLAPPING_TRANSITIONS", \
- M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS ),
-#ifdef M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ANALYSIS_DATA_SIZE_TOO_SMALL", \
- M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_3GPP_FILE", \
- M4VSS3GPP_ERR_INVALID_3GPP_FILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT", \
- M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT", \
- M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AMR_EDITING_UNSUPPORTED", \
- M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_VIDEO_AU_TOO_LARGE", \
- M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_AU_TOO_LARGE", \
- M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_CORRUPTED_AU", \
- M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU ),
-#ifdef M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_CORRUPTED_AU", \
- M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ENCODER_ACCES_UNIT_ERROR", \
- M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT", \
- M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_H263_PROFILE", \
- M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE", \
- M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_MPEG4_RVLC", \
- M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT", \
- M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE", \
- M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE",\
- M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_CLIP_ANALYSIS_VERSION", \
- M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION ),
-#ifdef M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_CLIP_ANALYSIS_PLATFORM", \
- M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_FORMAT", \
- M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE", \
- M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_TIME_SCALE", \
- M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING", \
- M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_MP3_ASSEMBLY", \
- M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NO_SUPPORTED_STREAM_IN_FILE", \
- M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ADDVOLUME_EQUALS_ZERO", \
- M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION", \
- M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT", \
- M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_ADDED_AUDIO_STREAM", \
- M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_MIXING_UNSUPPORTED", \
- M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED ),
-#ifdef M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_MIXING_MP3_UNSUPPORTED", \
- M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK", \
- M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK ),
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_AAC", \
- M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_CANNOT_BE_MIXED", \
- M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED ),
-#ifdef M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED", \
- M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_EVRC", \
- M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC ),
-#endif
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_H263_PROFILE_NOT_SUPPORTED", \
- M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE", \
- M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE ),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INTERNAL", \
- M4NO_ERROR ),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Error, ERROR_CLASS_NAME,
- videoEditClasses_getUnknownErrorName, videoEditClasses_getUnknownErrorString)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(FileType)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("THREE_GPP", VideoEditClasses_kFileType_3GPP),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MP4", VideoEditClasses_kFileType_MP4),
- VIDEOEDIT_JAVA_CONSTANT_INIT("AMR", VideoEditClasses_kFileType_AMR),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MP3", VideoEditClasses_kFileType_MP3),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PCM", VideoEditClasses_kFileType_PCM),
- VIDEOEDIT_JAVA_CONSTANT_INIT("JPG", VideoEditClasses_kFileType_JPG),
- VIDEOEDIT_JAVA_CONSTANT_INIT("GIF", VideoEditClasses_kFileType_GIF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PNG", VideoEditClasses_kFileType_PNG),
- VIDEOEDIT_JAVA_CONSTANT_INIT("M4V", VideoEditClasses_kFileType_M4V),
- VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", VideoEditClasses_kFileType_Unsupported)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(FileType, FILE_TYPE_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(MediaRendering)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("RESIZING", M4xVSS_kResizing),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CROPPING", M4xVSS_kCropping),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_BORDERS", M4xVSS_kBlackBorders)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(MediaRendering, MEDIA_RENDERING_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(SlideDirection)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("RIGHT_OUT_LEFT_IN", M4xVSS_SlideTransition_RightOutLeftIn),
- VIDEOEDIT_JAVA_CONSTANT_INIT("LEFT_OUT_RIGTH_IN", M4xVSS_SlideTransition_LeftOutRightIn),
- VIDEOEDIT_JAVA_CONSTANT_INIT("TOP_OUT_BOTTOM_IN", M4xVSS_SlideTransition_TopOutBottomIn),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BOTTOM_OUT_TOP_IN", M4xVSS_SlideTransition_BottomOutTopIn)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(SlideDirection, SLIDE_DIRECTION_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(TransitionBehaviour)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("SPEED_UP", M4VSS3GPP_TransitionBehaviour_SpeedUp),
- VIDEOEDIT_JAVA_CONSTANT_INIT("LINEAR", M4VSS3GPP_TransitionBehaviour_Linear),
- VIDEOEDIT_JAVA_CONSTANT_INIT("SPEED_DOWN", M4VSS3GPP_TransitionBehaviour_SpeedDown),
- VIDEOEDIT_JAVA_CONSTANT_INIT("SLOW_MIDDLE", M4VSS3GPP_TransitionBehaviour_SlowMiddle),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FAST_MIDDLE", M4VSS3GPP_TransitionBehaviour_FastMiddle)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(TransitionBehaviour, TRANSITION_BEHAVIOUR_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoEffect)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NONE", M4VSS3GPP_kVideoEffectType_None),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_FROM_BLACK", M4VSS3GPP_kVideoEffectType_FadeFromBlack),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_TO_BLACK", M4VSS3GPP_kVideoEffectType_FadeToBlack),
- VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL", M4VSS3GPP_kVideoEffectType_External),
- VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_AND_WHITE", M4xVSS_kVideoEffectType_BlackAndWhite),
- VIDEOEDIT_JAVA_CONSTANT_INIT("PINK", M4xVSS_kVideoEffectType_Pink),
- VIDEOEDIT_JAVA_CONSTANT_INIT("GREEN", M4xVSS_kVideoEffectType_Green),
- VIDEOEDIT_JAVA_CONSTANT_INIT("SEPIA", M4xVSS_kVideoEffectType_Sepia),
- VIDEOEDIT_JAVA_CONSTANT_INIT("NEGATIVE", M4xVSS_kVideoEffectType_Negative),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FRAMING", M4xVSS_kVideoEffectType_Framing),
- VIDEOEDIT_JAVA_CONSTANT_INIT("TEXT", M4xVSS_kVideoEffectType_Text),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ZOOM_IN", M4xVSS_kVideoEffectType_ZoomIn),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ZOOM_OUT", M4xVSS_kVideoEffectType_ZoomOut),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FIFTIES", M4xVSS_kVideoEffectType_Fifties),
- VIDEOEDIT_JAVA_CONSTANT_INIT("COLORRGB16", M4xVSS_kVideoEffectType_ColorRGB16),
- VIDEOEDIT_JAVA_CONSTANT_INIT("GRADIENT", M4xVSS_kVideoEffectType_Gradient),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoEffect, VIDEO_EFFECT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFormat)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NO_VIDEO", M4VIDEOEDITING_kNoneVideo),
- VIDEOEDIT_JAVA_CONSTANT_INIT("H263", M4VIDEOEDITING_kH263),
- VIDEOEDIT_JAVA_CONSTANT_INIT("MPEG4", M4VIDEOEDITING_kMPEG4),
- VIDEOEDIT_JAVA_CONSTANT_INIT("H264", M4VIDEOEDITING_kH264),
- VIDEOEDIT_JAVA_CONSTANT_INIT("NULL_VIDEO", M4VIDEOEDITING_kNullVideo),
- VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kUnsupportedVideo),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFormat, VIDEO_FORMAT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFrameRate)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_5_FPS", M4VIDEOEDITING_k5_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_7_5_FPS", M4VIDEOEDITING_k7_5_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_10_FPS", M4VIDEOEDITING_k10_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_12_5_FPS", M4VIDEOEDITING_k12_5_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_15_FPS", M4VIDEOEDITING_k15_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_20_FPS", M4VIDEOEDITING_k20_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_25_FPS", M4VIDEOEDITING_k25_FPS),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FR_30_FPS", M4VIDEOEDITING_k30_FPS)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameRate, VIDEO_FRAME_RATE_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFrameSize)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("SQCIF", M4VIDEOEDITING_kSQCIF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("QQVGA", M4VIDEOEDITING_kQQVGA),
- VIDEOEDIT_JAVA_CONSTANT_INIT("QCIF", M4VIDEOEDITING_kQCIF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("QVGA", M4VIDEOEDITING_kQVGA),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CIF", M4VIDEOEDITING_kCIF),
- VIDEOEDIT_JAVA_CONSTANT_INIT("VGA", M4VIDEOEDITING_kVGA),
- VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA", M4VIDEOEDITING_kWVGA),
- VIDEOEDIT_JAVA_CONSTANT_INIT("NTSC", M4VIDEOEDITING_kNTSC),
- VIDEOEDIT_JAVA_CONSTANT_INIT("nHD", M4VIDEOEDITING_k640_360),
- VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA16x9", M4VIDEOEDITING_k854_480),
- VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_k1280_720),
- VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_k1080_720),
- VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_k960_720),
- VIDEOEDIT_JAVA_CONSTANT_INIT("V1080p", M4VIDEOEDITING_k1920_1080)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameSize, VIDEO_FRAME_SIZE_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoTransition)
-{
- VIDEOEDIT_JAVA_CONSTANT_INIT("NONE", M4VSS3GPP_kVideoTransitionType_None),
- VIDEOEDIT_JAVA_CONSTANT_INIT("CROSS_FADE", M4VSS3GPP_kVideoTransitionType_CrossFade),
- VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL", M4VSS3GPP_kVideoTransitionType_External),
- VIDEOEDIT_JAVA_CONSTANT_INIT("ALPHA_MAGIC", M4xVSS_kVideoTransitionType_AlphaMagic),
- VIDEOEDIT_JAVA_CONSTANT_INIT("SLIDE_TRANSITION", M4xVSS_kVideoTransitionType_SlideTransition),
- VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_BLACK", M4xVSS_kVideoTransitionType_FadeBlack)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoTransition, VIDEO_TRANSITION_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(AlphaMagic)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("file", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("blendingPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("invertRotation", "Z" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rgbWidth", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rgbHeight", "I" )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(AlphaMagic, ALPHA_MAGIC_SETTINGS_CLASS_NAME)
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Properties)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("duration", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("fileType", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("videoFormat", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("videoDuration", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("videoBitrate", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("width", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("height", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("averageFrameRate", "F"),
- VIDEOEDIT_JAVA_FIELD_INIT("profile", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("level", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("profileSupported", "Z"),
- VIDEOEDIT_JAVA_FIELD_INIT("levelSupported", "Z"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioFormat", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioDuration", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioBitrate", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioChannels", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioSamplingFrequency", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("videoRotation", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Properties, PROPERTIES_CLASS_NAME)
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(BackgroundMusic)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("file", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("fileType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("insertionTime", "J" ),
- VIDEOEDIT_JAVA_FIELD_INIT("volumePercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("beginLoop", "J" ),
- VIDEOEDIT_JAVA_FIELD_INIT("endLoop", "J" ),
- VIDEOEDIT_JAVA_FIELD_INIT("enableDucking", "Z" ),
- VIDEOEDIT_JAVA_FIELD_INIT("duckingThreshold","I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("lowVolume", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("isLooping", "Z" )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(BackgroundMusic, BACKGROUND_MUSIC_SETTINGS_CLASS_NAME)
-
-/*
-VIDEOEDIT_JAVA_DEFINE_FIELDS(BestEditSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("videoFormat", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("videoFrameSize", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioFormat", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("audioChannels", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(BestEditSettings, BEST_EDIT_SETTINGS_CLASS_NAME)
-*/
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(ClipSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("clipPath", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("fileType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("beginCutTime", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("endCutTime", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("beginCutPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("endCutPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomEnabled", "Z" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomPercentStart", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftXStart", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftYStart", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomPercentEnd", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftXEnd", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftYEnd", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("mediaRendering", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rgbWidth", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rgbHeight", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rotationDegree", "I" )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(ClipSettings, CLIP_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(EditSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("clipSettingsArray", "[L"CLIP_SETTINGS_CLASS_NAME";" ),
- VIDEOEDIT_JAVA_FIELD_INIT("transitionSettingsArray", "[L"TRANSITION_SETTINGS_CLASS_NAME";" ),
- VIDEOEDIT_JAVA_FIELD_INIT("effectSettingsArray", "[L"EFFECT_SETTINGS_CLASS_NAME";" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoFrameRate", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("outputFile", "Ljava/lang/String;" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoFrameSize", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoFormat", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoProfile", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoLevel", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioFormat", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioSamplingFreq", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("maxFileSize", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioChannels", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoBitrate", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioBitrate", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("backgroundMusicSettings",\
- "L"BACKGROUND_MUSIC_SETTINGS_CLASS_NAME";"),
- VIDEOEDIT_JAVA_FIELD_INIT("primaryTrackVolume", "I" )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(EditSettings, EDIT_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(EffectSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("startTime", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("duration", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoEffectType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioEffectType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("startPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("durationPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("framingFile", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("framingBuffer", "[I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("bitmapType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("width", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("height", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("topLeftX", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("topLeftY", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("framingResize", "Z" ),
- VIDEOEDIT_JAVA_FIELD_INIT("framingScaledSize", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("text", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("textRenderingData", "Ljava/lang/String;"),
- VIDEOEDIT_JAVA_FIELD_INIT("textBufferWidth", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("textBufferHeight", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("fiftiesFrameRate", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("rgb16InputColor", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingStartPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingMiddlePercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingEndPercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingFadeInTimePercent", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingFadeOutTimePercent", "I" )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(EffectSettings, EFFECT_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Engine)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("mManualEditContext", "J")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(SlideTransitionSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("direction", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(SlideTransitionSettings, SLIDE_TRANSITION_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(TransitionSettings)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("duration", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("videoTransitionType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("audioTransitionType", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("transitionBehaviour", "I" ),
- VIDEOEDIT_JAVA_FIELD_INIT("alphaSettings", "L"ALPHA_MAGIC_SETTINGS_CLASS_NAME";" ),
- VIDEOEDIT_JAVA_FIELD_INIT("slideSettings", "L"SLIDE_TRANSITION_SETTINGS_CLASS_NAME";")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(TransitionSettings, TRANSITION_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Version)
-{
- VIDEOEDIT_JAVA_FIELD_INIT("major", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("minor", "I"),
- VIDEOEDIT_JAVA_FIELD_INIT("revision", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Version, VERSION_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_METHODS(Engine)
-{
- VIDEOEDIT_JAVA_METHOD_INIT("onProgressUpdate", "(II)V")
-};
-
-VIDEOEDIT_JAVA_DEFINE_METHOD_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME)
-
-
-static const char*
-videoEditClasses_getBrandString(M4OSA_UInt32 brand)
-{
- static char brandString[11] = "0x00000000";
- const char* pBrandString = M4OSA_NULL;
- M4OSA_UInt8* pBrand = (M4OSA_UInt8*)&brand;
- M4OSA_UInt32 brandHost = 0;
-
- // Convert the brand from big endian to host.
- brandHost = pBrand[0];
- brandHost = brandHost << 8;
- brandHost += pBrand[1];
- brandHost = brandHost << 8;
- brandHost += pBrand[2];
- brandHost = brandHost << 8;
- brandHost += pBrand[3];
-
- switch (brandHost)
- {
- case M4VIDEOEDITING_BRAND_0000:
- pBrandString = "0000";
- break;
- case M4VIDEOEDITING_BRAND_3G2A:
- pBrandString = "3G2A";
- break;
- case M4VIDEOEDITING_BRAND_3GP4:
- pBrandString = "3GP4";
- break;
- case M4VIDEOEDITING_BRAND_3GP5:
- pBrandString = "3GP5";
- break;
- case M4VIDEOEDITING_BRAND_3GP6:
- pBrandString = "3GP6";
- break;
- case M4VIDEOEDITING_BRAND_AVC1:
- pBrandString = "AVC1";
- break;
- case M4VIDEOEDITING_BRAND_EMP:
- pBrandString = "EMP";
- break;
- case M4VIDEOEDITING_BRAND_ISOM:
- pBrandString = "ISOM";
- break;
- case M4VIDEOEDITING_BRAND_MP41:
- pBrandString = "MP41";
- break;
- case M4VIDEOEDITING_BRAND_MP42:
- pBrandString = "MP42";
- break;
- case M4VIDEOEDITING_BRAND_VFJ1:
- pBrandString = "VFJ1";
- break;
- default:
- M4OSA_chrSPrintf((M4OSA_Char *)brandString,
- sizeof(brandString) - 1,
- (M4OSA_Char*)"0x%08X", brandHost);
- pBrandString = brandString;
- break;
- }
-
- // Return the brand string.
- return(pBrandString);
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-static void
-videoEditClasses_logFtypBox(
- M4VIDEOEDITING_FtypBox* pBox,
- int indentation)
-{
- // Check if memory was allocated for the FtypBox.
- if (M4OSA_NULL != pBox)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c major_brand: %s", indentation, ' ',
- videoEditClasses_getBrandString(pBox->major_brand));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c minor_version: %08X", indentation, ' ',
- (unsigned int)pBox->minor_version);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c nbCompatibleBrands: %u", indentation, ' ',
- (unsigned int)pBox->nbCompatibleBrands);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c compatible_brands:", indentation, ' ');
- indentation += VIDEOEDIT_LOG_INDENTATION;
- for (int i = 0; (i < (int)pBox->nbCompatibleBrands) &&\
- (i < M4VIDEOEDITING_MAX_COMPATIBLE_BRANDS); i++)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c compatible_brand[%d]: %s", indentation, ' ',
- i, videoEditClasses_getBrandString(pBox->compatible_brands[i]));
- }
- indentation -= VIDEOEDIT_LOG_INDENTATION;
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
- indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_init(
- bool* pResult,
- JNIEnv* pEnv)
-{
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",\
- "videoEditClasses_init()");
-
- // Initialize the constants.
- videoEditJava_initAudioEffectConstants(pResult, pEnv);
- videoEditJava_initAudioFormatConstants(pResult, pEnv);
- videoEditJava_initAudioSamplingFrequencyConstants(pResult, pEnv);
- videoEditJava_initAudioTransitionConstants(pResult, pEnv);
- videoEditJava_initBitrateConstants(pResult, pEnv);
- videoEditJava_initClipTypeConstants(pResult, pEnv);
- videoEditJava_initEngineConstants(pResult, pEnv);
- videoEditJava_initErrorConstants(pResult, pEnv);
- videoEditJava_initFileTypeConstants(pResult, pEnv);
- videoEditJava_initMediaRenderingConstants(pResult, pEnv);
- videoEditJava_initSlideDirectionConstants(pResult, pEnv);
- videoEditJava_initTransitionBehaviourConstants(pResult, pEnv);
- videoEditJava_initVideoEffectConstants(pResult, pEnv);
- videoEditJava_initVideoFormatConstants(pResult, pEnv);
- videoEditJava_initVideoFrameRateConstants(pResult, pEnv);
- videoEditJava_initVideoFrameSizeConstants(pResult, pEnv);
- videoEditJava_initVideoTransitionConstants(pResult, pEnv);
-
- // Initialize the fields.
- videoEditJava_initAlphaMagicFields(pResult, pEnv);
- videoEditJava_initBackgroundMusicFields(pResult, pEnv);
- videoEditJava_initClipSettingsFields(pResult, pEnv);
- videoEditJava_initEditSettingsFields(pResult, pEnv);
- videoEditJava_initEffectSettingsFields(pResult, pEnv);
- videoEditJava_initEngineFields(pResult, pEnv);
- videoEditJava_initSlideTransitionSettingsFields(pResult, pEnv);
- videoEditJava_initTransitionSettingsFields(pResult, pEnv);
- videoEditJava_initVersionFields(pResult, pEnv);
- // Initialize the methods.
- videoEditJava_initEngineMethods(pResult, pEnv);
- }
-}
-
-void
-videoEditPropClass_init(
- bool* pResult,
- JNIEnv* pEnv)
-{
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",\
- "videoEditPropClass_init()");
-
- // Initialize the constants.
- videoEditJava_initAudioFormatConstants(pResult, pEnv);
- videoEditJava_initErrorConstants(pResult, pEnv);
- videoEditJava_initFileTypeConstants(pResult, pEnv);
- videoEditJava_initVideoFormatConstants(pResult, pEnv);
-
- // Initialize the fields.
- videoEditJava_initPropertiesFields(pResult, pEnv);
- }
-}
-
-void
-videoEditClasses_getAlphaMagicSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_AlphaMagicSettings** ppSettings)
-{
- VideoEditJava_AlphaMagicFieldIds fieldIds;
- M4xVSS_AlphaMagicSettings* pSettings = M4OSA_NULL;
- memset(&fieldIds, 0, sizeof(VideoEditJava_AlphaMagicFieldIds));
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getAlphaMagicSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getAlphaMagicFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only validate the AlphaMagicSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the clip is set.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (NULL == object),
- "alphaSettings is null");
- }
-
- // Only retrieve the AlphaMagicSettings if the fields could be located and validated.
- if (*pResult)
- {
- // Allocate memory for the AlphaMagicSettings.
- pSettings = (M4xVSS_AlphaMagicSettings*)videoEditOsal_alloc(pResult, pEnv,
- sizeof(M4xVSS_AlphaMagicSettings), "AlphaMagicSettings");
-
- // Check if memory could be allocated for the AlphaMagicSettings.
- if (*pResult)
- {
- // Set the alpha magic file path (JPG file).
- pSettings->pAlphaFilePath = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
- fieldIds.file, M4OSA_NULL);
-
- // Check if the alpha magic file path is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (M4OSA_NULL == pSettings->pAlphaFilePath), "alphaSettings.file is null");
- }
-
- // Check if the alpha file path could be retrieved.
- if (*pResult)
- {
- // Set the blending percentage between 0 and 100.
- pSettings->blendingPercent = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.blendingPercent);
-
- // Set the direct effect or reverse.
- pSettings->isreverse = (M4OSA_Bool)pEnv->GetBooleanField(object,
- fieldIds.invertRotation);
-
- // Get the rgb width
- pSettings->width = (M4OSA_UInt32) pEnv->GetIntField(object, fieldIds.rgbWidth );
-
- pSettings->height = (M4OSA_UInt32) pEnv->GetIntField(object, fieldIds.rgbHeight );
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "((((((((((path %s", pSettings->pAlphaFilePath);
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "------- getAlphaMagicSettings width %d", pEnv->GetIntField(object,
- fieldIds.rgbWidth ));
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "-------- getAlphaMagicSettings Height %d",
- pEnv->GetIntField(object, fieldIds.rgbHeight ));
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeAlphaMagicSettings(&pSettings);
- }
- }
-}
-
-void
-videoEditClasses_freeAlphaMagicSettings(
- M4xVSS_AlphaMagicSettings** ppSettings)
-{
- // Check if memory was allocated for the AlphaMagicSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeAlphaMagicSettings()");
-
- // Free the alpha file path.
- videoEditOsal_free((*ppSettings)->pAlphaFilePath);
- (*ppSettings)->pAlphaFilePath = M4OSA_NULL;
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logAlphaMagicSettings(
- M4xVSS_AlphaMagicSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the AlphaMagicSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pAlphaFilePath: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pAlphaFilePath) ? \
- (char *)pSettings->pAlphaFilePath : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c blendingPercent: %u %%", indentation, ' ',
- (unsigned int)pSettings->blendingPercent);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c isreverse: %s", indentation, ' ',
- pSettings->isreverse ? "true" : "false");
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_getBackgroundMusicSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_BGMSettings** ppSettings)
-{
- VideoEditJava_BackgroundMusicFieldIds fieldIds;
- M4xVSS_BGMSettings* pSettings = M4OSA_NULL;
- bool converted = true;
- memset(&fieldIds, 0, sizeof(VideoEditJava_BackgroundMusicFieldIds));
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getBackgroundMusicSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getBackgroundMusicFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only retrieve the BackgroundMusicSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the object is valid.
- if (NULL != object)
- {
- // Allocate memory for the BackgroundMusicSettings.
- pSettings = (M4xVSS_BGMSettings*)videoEditOsal_alloc(pResult, pEnv,
- sizeof(M4xVSS_BGMSettings), "BackgroundMusicSettings");
-
- // Check if memory could be allocated for the BackgroundMusicSettings.
- if (*pResult)
- {
- // Set the input file path.
- pSettings->pFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
- fieldIds.file, M4OSA_NULL);
-
- // Check if the input file path is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (M4OSA_NULL == pSettings->pFile), "backgroundMusicSettings.file is null");
- }
-
- // Check if the input file path could be retrieved.
- if (*pResult)
- {
- // Set the file type .3gp, .amr, .mp3.
- pSettings->FileType = M4VIDEOEDITING_kFileType_PCM;
- /*(M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.fileType));*/
-
- // Check if the file type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "backgroundMusicSettings.fileType is invalid");
- }
-
- // Check if the file type could be retrieved.
- if (*pResult)
- {
- // Set the time, in milliseconds, at which the added audio track is inserted.
- pSettings->uiAddCts = (M4OSA_UInt32)pEnv->GetLongField(object,
- fieldIds.insertionTime);
-
- // Set the volume, in percentage (0..100), of the added audio track.
- pSettings->uiAddVolume = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.volumePercent);
-
- // Set the start time of the loop in milli seconds.
- pSettings->uiBeginLoop = (M4OSA_UInt32)pEnv->GetLongField(object,
- fieldIds.beginLoop);
-
- // Set the end time of the loop in milli seconds.
- pSettings->uiEndLoop = (M4OSA_UInt32)pEnv->GetLongField(object,
- fieldIds.endLoop);
- // Set the end time of the loop in milli seconds.
- pSettings->b_DuckingNeedeed =
- (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.enableDucking);
-
- // Set the end time of the loop in milli seconds.
- pSettings->InDucking_threshold =
- (M4OSA_Int32)pEnv->GetIntField(object, fieldIds.duckingThreshold);
-
- // Set the end time of the loop in milli seconds.
- pSettings->lowVolume =
- (M4OSA_Float)(((M4OSA_Float)pEnv->GetIntField(object, fieldIds.lowVolume)));
-
- // Set the end time of the loop in milli seconds.
- pSettings->bLoop = (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.isLooping);
-
- // Set sampling freq and channels
- pSettings->uiSamplingFrequency = M4VIDEOEDITING_k32000_ASF;
- pSettings->uiNumChannels = 2;
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeBackgroundMusicSettings(&pSettings);
- }
- }
- }
-}
-
-void
-videoEditClasses_freeBackgroundMusicSettings(
- M4xVSS_BGMSettings** ppSettings)
-{
- // Check if memory was allocated for the BackgroundMusicSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeBackgroundMusicSettings()");
-
- // Free the input file path.
- videoEditOsal_free((*ppSettings)->pFile);
- (*ppSettings)->pFile = M4OSA_NULL;
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logBackgroundMusicSettings(
- M4xVSS_BGMSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the BackgroundMusicSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c pFile: %s",
- indentation, ' ',
- (M4OSA_NULL != pSettings->pFile) ? (char *)pSettings->pFile : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c FileType: %s", indentation, ' ',
- videoEditJava_getClipTypeString(pSettings->FileType));
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiAddCts: %u ms",
- indentation, ' ', (unsigned int)pSettings->uiAddCts);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiAddVolume: %u %%",
- indentation, ' ', (unsigned int)pSettings->uiAddVolume);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiBeginLoop: %u ms",
- indentation, ' ', (unsigned int)pSettings->uiBeginLoop);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiEndLoop: %u ms",
- indentation, ' ', (unsigned int)pSettings->uiEndLoop);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c b_DuckingNeedeed:\
- %u ", indentation, ' ', (bool)pSettings->b_DuckingNeedeed);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c InDucking_threshold: \
- %u ms", indentation, ' ', (unsigned int)pSettings->InDucking_threshold);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c lowVolume: %2.2f ",\
- indentation, ' ', (float)pSettings->lowVolume);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c bLoop: %u ms",\
- indentation, ' ', (bool)pSettings->bLoop);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
- indentation, ' ');
- }
-}
-#endif
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logClipProperties(
- M4VIDEOEDITING_ClipProperties* pProperties,
- int indentation)
-{
- // Check if memory was allocated for the ClipProperties.
- if (M4OSA_NULL != pProperties)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bAnalysed: %s", indentation, ' ',
- pProperties->bAnalysed ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c Version: %d.%d.%d", indentation, ' ',
- pProperties->Version[0], pProperties->Version[1], pProperties->Version[2]);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiClipDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c FileType: %s", indentation, ' ',
- videoEditJava_getClipTypeString(pProperties->FileType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c ftyp:",
- indentation, ' ');
- videoEditClasses_logFtypBox(&pProperties->ftyp, indentation + VIDEOEDIT_LOG_INDENTATION);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c VideoStreamType: %s", indentation, ' ',
- videoEditJava_getVideoFormatString(pProperties->VideoStreamType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiClipVideoDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipVideoDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiVideoBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pProperties->uiVideoBitrate));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiVideoMaxAuSize: %u", indentation, ' ',
- (unsigned int)pProperties->uiVideoMaxAuSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiVideoWidth: %u", indentation, ' ',
- (unsigned int)pProperties->uiVideoWidth);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiVideoHeight: %u", indentation, ' ',
- (unsigned int)(unsigned int)pProperties->uiVideoHeight);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiVideoTimeScale: %u", indentation, ' ',
- (unsigned int)pProperties->uiVideoTimeScale);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c fAverageFrameRate: %.3f", indentation, ' ',
- pProperties->fAverageFrameRate);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bMPEG4dataPartition: %s", indentation, ' ',
- pProperties->bMPEG4dataPartition ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bMPEG4rvlc: %s", indentation, ' ',
- pProperties->bMPEG4rvlc ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bMPEG4resynchMarker: %s", indentation, ' ',
- pProperties->bMPEG4resynchMarker ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c AudioStreamType: %s", indentation, ' ',
- videoEditJava_getAudioFormatString(pProperties->AudioStreamType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiClipAudioDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipAudioDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiAudioBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pProperties->uiAudioBitrate));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiAudioMaxAuSize: %u", indentation, ' ',
- (unsigned int)pProperties->uiAudioMaxAuSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiNbChannels: %u", indentation, ' ',
- (unsigned int)pProperties->uiNbChannels);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiSamplingFrequency: %u", indentation, ' ',
- (unsigned int)pProperties->uiSamplingFrequency);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiExtendedSamplingFrequency: %u", indentation, ' ',
- (unsigned int)pProperties->uiExtendedSamplingFrequency);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiDecodedPcmSize: %u", indentation, ' ',
- (unsigned int)pProperties->uiDecodedPcmSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bVideoIsEditable: %s", indentation, ' ',
- pProperties->bVideoIsEditable ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bAudioIsEditable: %s", indentation, ' ',
- pProperties->bAudioIsEditable ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bVideoIsCompatibleWithMasterClip: %s", indentation, ' ',
- pProperties->bVideoIsCompatibleWithMasterClip ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bAudioIsCompatibleWithMasterClip: %s", indentation, ' ',
- pProperties->bAudioIsCompatibleWithMasterClip ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiClipAudioVolumePercentage: %d", indentation, ' ',
- pProperties->uiClipAudioVolumePercentage);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
- indentation, ' ');
- }
-}
-#endif
-
-void
-videoEditClasses_getClipSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_ClipSettings** ppSettings)
-{
-
- VideoEditJava_ClipSettingsFieldIds fieldIds;
- M4VSS3GPP_ClipSettings* pSettings = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
- bool converted = true;
- memset(&fieldIds, 0, sizeof(VideoEditJava_ClipSettingsFieldIds));
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getClipSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getClipSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only validate the ClipSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the clip is set.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (NULL == object),
- "clip is null");
- }
-
- // Only retrieve the ClipSettings if the fields could be located and validated.
- if (*pResult)
- {
- // Allocate memory for the ClipSettings.
- pSettings = (M4VSS3GPP_ClipSettings *)videoEditOsal_alloc(pResult, pEnv,
- sizeof(M4VSS3GPP_ClipSettings), "ClipSettings");
-
- // Check if memory could be allocated for the ClipSettings.
- if (*pResult)
- {
- // Log the API call.
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4xVSS_CreateClipSettings()");
-
- // Initialize the ClipSettings.
- result = M4xVSS_CreateClipSettings(pSettings, NULL, 0, 0);
-
- // Log the result.
- VIDEOEDIT_LOG_RESULT(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- videoEditOsal_getResultString(result));
-
- // Check if the initialization succeeded.
- videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
- (M4NO_ERROR != result), result);
- }
-
- // Check if the allocation and initialization succeeded
- //(required because pSettings is dereferenced).
- if (*pResult)
- {
- // Set the input file path.
- pSettings->pFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
- fieldIds.clipPath, &pSettings->filePathSize);
-
- // Check if the file path is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (M4OSA_NULL == pSettings->pFile), "clip.clipPath is null");
- }
-
- // Check if the input file could be retrieved.
- if (*pResult)
- {
- // Set the file type .3gp, .amr, .mp3.
- pSettings->FileType = (M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.fileType));
-
- if (( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG) ||
- ( pSettings->FileType == M4VIDEOEDITING_kFileType_PNG)) {
- pSettings->FileType = M4VIDEOEDITING_kFileType_ARGB8888;
- }
-
- // Check if the file type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "clip.fileType is invalid");
- }
-
- // Check if the file type could be retrieved.
- if (*pResult)
- {
- // Set the begin cut time, in milliseconds.
- pSettings->uiBeginCutTime =
- (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.beginCutTime);
-
- // Set the end cut time, in milliseconds.
- pSettings->uiEndCutTime = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.endCutTime);
-
- // Set the begin cut time, in percent of clip duration (only for 3GPP clip !).
- pSettings->xVSS.uiBeginCutPercent =
- (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.beginCutPercent);
-
- // Set the end cut time, in percent of clip duration (only for 3GPP clip !).
- pSettings->xVSS.uiEndCutPercent =
- (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.endCutPercent);
-
- // Set the duration of the clip, if different from 0,
- // has priority on uiEndCutTime or uiEndCutPercent.
- pSettings->xVSS.uiDuration = 0;
-
- // Set whether or not the pan and zoom mode is enabled.
- pSettings->xVSS.isPanZoom =
- (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.panZoomEnabled);
-
- // Set the pan and zoom start zoom percentage.
- pSettings->xVSS.PanZoomXa =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomPercentStart);
-
- // Set the pan and zoom start x.
- pSettings->xVSS.PanZoomTopleftXa =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftXStart);
-
- // Set the pan and zoom start y.
- pSettings->xVSS.PanZoomTopleftYa =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftYStart);
-
- // Set the pan and zoom end zoom percentage.
- pSettings->xVSS.PanZoomXb =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomPercentEnd);
-
- // Set the pan and zoom end x.
- pSettings->xVSS.PanZoomTopleftXb =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftXEnd);
-
- // Set the pan and zoom end y.
- pSettings->xVSS.PanZoomTopleftYb =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftYEnd);
-
- // Set the media rendering mode, only used with JPEG to crop, resize,
- // or render black borders.
- pSettings->xVSS.MediaRendering =
- (M4xVSS_MediaRendering)videoEditJava_getMediaRenderingJavaToC(
- &converted, pEnv->GetIntField(object,fieldIds.mediaRendering));
-
- // Check if the media rendering is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
- "clip.mediaRendering is invalid");
-
- // Capture the rgb file width and height
- pSettings->ClipProperties.uiStillPicWidth =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.rgbFileWidth);
- pSettings->ClipProperties.uiStillPicHeight =
- (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.rgbFileHeight);
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", \
- "getClipSettings-- rgbFileWidth %d ",
- pSettings->ClipProperties.uiStillPicWidth);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", \
- "getClipSettings-- rgbFileHeight %d ",
- pSettings->ClipProperties.uiStillPicHeight);
-
- // Set the video rotation degree
- pSettings->ClipProperties.videoRotationDegrees =
- (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.rotationDegree);
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeClipSettings(&pSettings);
- }
- }
-}
-
-void
-videoEditClasses_createClipSettings(
- bool* pResult,
- JNIEnv* pEnv,
- M4VSS3GPP_ClipSettings* pSettings,
- jobject* pObject)
-{
- VideoEditJava_ClipSettingsFieldIds fieldIds;
- jclass clazz = NULL;
- jobject object = NULL;
- memset(&fieldIds, 0, sizeof(VideoEditJava_ClipSettingsFieldIds));
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_createClipSettings()");
-
- // Retrieve the class.
- videoEditJava_getClipSettingsClass(pResult, pEnv, &clazz);
-
- // Retrieve the field ids.
- videoEditJava_getClipSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only create an object if the class and fields could be located.
- if (*pResult)
- {
- // Allocate a new object.
- object = pEnv->AllocObject(clazz);
- if (NULL != object)
- {
- // Set the clipPath field.
- pEnv->SetObjectField(object, fieldIds.clipPath, NULL);
-
- // Set the fileType field.
- pEnv->SetIntField(object, fieldIds.fileType, videoEditJava_getClipTypeCToJava(
- pSettings->FileType));
-
- // Set the beginCutTime field.
- pEnv->SetIntField(object, fieldIds.beginCutTime, pSettings->uiBeginCutTime);
-
- // Set the endCutTime field.
- pEnv->SetIntField(object, fieldIds.endCutTime, pSettings->uiEndCutTime);
-
- // Set the beginCutPercent field.
- pEnv->SetIntField(object, fieldIds.beginCutPercent, pSettings->xVSS.uiBeginCutPercent);
-
- // Set the endCutPercent field.
- pEnv->SetIntField(object, fieldIds.endCutPercent, pSettings->xVSS.uiEndCutPercent);
-
- // Set the panZoomEnabled field.
- pEnv->SetBooleanField(object, fieldIds.panZoomEnabled, pSettings->xVSS.isPanZoom);
-
- // Set the panZoomPercentStart field.
- pEnv->SetIntField(object, fieldIds.panZoomPercentStart,
- (1000 - pSettings->xVSS.PanZoomXa));
-
- // Set the panZoomTopLeftXStart field.
- pEnv->SetIntField(object, fieldIds.panZoomTopLeftXStart,
- pSettings->xVSS.PanZoomTopleftXa);
-
- // Set the panZoomTopLeftYStart field.
- pEnv->SetIntField(object, fieldIds.panZoomTopLeftYStart,
- pSettings->xVSS.PanZoomTopleftYa);
-
- // Set the panZoomPercentEnd field.
- pEnv->SetIntField(object, fieldIds.panZoomPercentEnd,
- (1000 - pSettings->xVSS.PanZoomXb));
-
- // Set the panZoomTopLeftXEnd field.
- pEnv->SetIntField(object, fieldIds.panZoomTopLeftXEnd,
- pSettings->xVSS.PanZoomTopleftXb);
-
- // Set the panZoomTopLeftYEnd field.
- pEnv->SetIntField(object, fieldIds.panZoomTopLeftYEnd,
- pSettings->xVSS.PanZoomTopleftYb);
-
- // Set the mediaRendering field.
- pEnv->SetIntField(object, fieldIds.mediaRendering,
- videoEditJava_getMediaRenderingCToJava(pSettings->xVSS.MediaRendering));
-
- // Set the rgb file width and height
- pEnv->SetIntField(object, fieldIds.rgbFileWidth,
- pSettings->ClipProperties.uiStillPicWidth );
-
- pEnv->SetIntField(object, fieldIds.rgbFileHeight,
- pSettings->ClipProperties.uiStillPicHeight );
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "rgbFileWeight %d rgbFileHeight %d ",
- pSettings->ClipProperties.uiStillPicWidth ,
- pSettings->ClipProperties.uiStillPicHeight);
-
- // Set the video rotation
- pEnv->SetIntField(object, fieldIds.rotationDegree,
- pSettings->ClipProperties.videoRotationDegrees);
-
- // Return the object.
- (*pObject) = object;
- }
- }
-}
-void
-videoEditPropClass_createProperties(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditPropClass_Properties* pProperties,
- jobject* pObject)
-{
- VideoEditJava_PropertiesFieldIds fieldIds;
- jclass clazz = NULL;
- jobject object = NULL;
- memset(&fieldIds, 0, sizeof(VideoEditJava_PropertiesFieldIds));
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "videoEditPropClass_createProperties()");
-
- // Retrieve the class.
- videoEditJava_getPropertiesClass(pResult, pEnv, &clazz);
-
- // Retrieve the field ids.
- videoEditJava_getPropertiesFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only create an object if the class and fields could be located.
- if (*pResult)
- {
- // Allocate a new object.
- object = pEnv->AllocObject(clazz);
- if (NULL != object)
- {
- // Set the duration field.
- pEnv->SetIntField(object, fieldIds.duration, pProperties->uiClipDuration);
-
- // Set the fileType field.
- pEnv->SetIntField(object, fieldIds.fileType,
- videoEditJava_getFileTypeCToJava(pProperties->FileType));
-
- // Set the videoFormat field.
- pEnv->SetIntField(object, fieldIds.videoFormat,
- videoEditJava_getVideoFormatCToJava(pProperties->VideoStreamType));
-
- // Set the videoDuration field.
- pEnv->SetIntField(object, fieldIds.videoDuration, pProperties->uiClipVideoDuration);
-
- // Set the videoBitrate field.
- pEnv->SetIntField(object, fieldIds.videoBitrate, pProperties->uiVideoBitrate);
-
- // Set the width field.
- pEnv->SetIntField(object, fieldIds.width, pProperties->uiVideoWidth);
-
- // Set the height field.
- pEnv->SetIntField(object, fieldIds.height, pProperties->uiVideoHeight);
-
- // Set the averageFrameRate field.
- pEnv->SetFloatField(object, fieldIds.averageFrameRate, pProperties->fAverageFrameRate);
-
- // Set the profile field.
- pEnv->SetIntField(object, fieldIds.profile,
- pProperties->uiVideoProfile);
-
- // Set the level field.
- pEnv->SetIntField(object, fieldIds.level,
- pProperties->uiVideoLevel);
-
- // Set whether profile supported
- pEnv->SetBooleanField(object, fieldIds.profileSupported,
- pProperties->bProfileSupported);
-
- // Set whether level supported
- pEnv->SetBooleanField(object, fieldIds.levelSupported,
- pProperties->bLevelSupported);
-
- // Set the audioFormat field.
- pEnv->SetIntField(object, fieldIds.audioFormat,
- videoEditJava_getAudioFormatCToJava(pProperties->AudioStreamType));
-
- // Set the audioDuration field.
- pEnv->SetIntField(object, fieldIds.audioDuration, pProperties->uiClipAudioDuration);
-
- // Set the audioBitrate field.
- pEnv->SetIntField(object, fieldIds.audioBitrate, pProperties->uiAudioBitrate);
-
- // Set the audioChannels field.
- pEnv->SetIntField(object, fieldIds.audioChannels, pProperties->uiNbChannels);
-
- // Set the audioSamplingFrequency field.
- pEnv->SetIntField(object, fieldIds.audioSamplingFrequency,
- pProperties->uiSamplingFrequency);
-
- // Set the video rotation field.
- pEnv->SetIntField(object, fieldIds.videoRotation, pProperties->uiRotation);
-
- // Return the object.
- (*pObject) = object;
- }
- }
-}
-
-void
-videoEditClasses_freeClipSettings(
- M4VSS3GPP_ClipSettings** ppSettings)
-{
- // Check if memory was allocated for the ClipSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeClipSettings()");
-
- // Free the input file path.
- videoEditOsal_free((*ppSettings)->pFile);
- (*ppSettings)->pFile = M4OSA_NULL;
- (*ppSettings)->filePathSize = 0;
-
- // Free the clip settings.
- M4xVSS_FreeClipSettings((*ppSettings));
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logClipSettings(
- M4VSS3GPP_ClipSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the ClipSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pFile: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pFile) ? (char*)pSettings->pFile : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c FileType: %s", indentation, ' ',
- videoEditJava_getClipTypeString(pSettings->FileType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c filePathSize: %u", indentation, ' ',
- (unsigned int)pSettings->filePathSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c ClipProperties:", indentation, ' ');
- videoEditClasses_logClipProperties(&pSettings->ClipProperties,
- indentation + VIDEOEDIT_LOG_INDENTATION);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiBeginCutTime: %u ms", indentation, ' ',
- (unsigned int)pSettings->uiBeginCutTime);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiEndCutTime: %u ms", indentation, ' ',
- (unsigned int)pSettings->uiEndCutTime);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiBeginCutPercent: %u %%", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiBeginCutPercent);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiEndCutPercent: %u %%", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiEndCutPercent);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiDuration: %u ms", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c isPanZoom: %s", indentation, ' ',
- pSettings->xVSS.isPanZoom ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomXa: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomXa);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomTopleftXa: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomTopleftXa);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomTopleftYa: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomTopleftYa);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomXb: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomXb);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomTopleftXb: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomTopleftXb);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PanZoomTopleftYb: %d ms", indentation, ' ',
- pSettings->xVSS.PanZoomTopleftYb);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c MediaRendering: %s", indentation, ' ',
- videoEditJava_getMediaRenderingString(pSettings->xVSS.MediaRendering));
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_getEditSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_EditSettings** ppSettings,
- bool flag)
-{
- VideoEditJava_EditSettingsFieldIds fieldIds;
- jobjectArray clipSettingsArray = NULL;
- jsize clipSettingsArraySize = 0;
- jobject clipSettings = NULL;
- jobjectArray transitionSettingsArray = NULL;
- jsize transitionSettingsArraySize = 0;
- jobject transitionSettings = NULL;
- jobjectArray effectSettingsArray = NULL;
- jsize effectSettingsArraySize = 0;
- jobject effectSettings = NULL;
- jobject backgroundMusicSettings = NULL;
- int audioChannels = 0;
- M4VSS3GPP_EditSettings* pSettings = M4OSA_NULL;
- bool converted = true;
- memset(&fieldIds, 0, sizeof(VideoEditJava_EditSettingsFieldIds));
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getEditSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getEditSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only retrieve the EditSettings if the previous action succeeded.
- if (*pResult)
- {
- // Check if the object is valid.
- if (NULL != object)
- {
- // Retrieve the clipSettingsArray.
- videoEditJava_getArray(pResult, pEnv, object,
- fieldIds.clipSettingsArray,
- &clipSettingsArray,
- &clipSettingsArraySize);
-
- // Retrieve the transitionSettingsArray.
- videoEditJava_getArray(pResult, pEnv, object,
- fieldIds.transitionSettingsArray,
- &transitionSettingsArray,
- &transitionSettingsArraySize);
-
- // Retrieve the effectSettingsArray.
- videoEditJava_getArray(pResult, pEnv, object,
- fieldIds.effectSettingsArray,
- &effectSettingsArray,
- &effectSettingsArraySize);
-
- // Retrieve the backgroundMusicSettings.
- videoEditJava_getObject(pResult, pEnv, object, fieldIds.backgroundMusicSettings,
- &backgroundMusicSettings);
-
- // Check if the arrays and background music settings object could be retrieved.
- if (*pResult)
- {
- // Retrieve the number of channels.
- audioChannels = pEnv->GetIntField(object, fieldIds.audioChannels);
- }
- }
- }
-
- // Only validate the EditSettings if the fields could be located.
- if (*pResult)
- {
- // Check if there is at least one clip.
- //videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- // (clipSettingsArraySize < 1),
- // "there should be at least one clip");
- if(clipSettingsArraySize < 1) {
- return;
- }
- if(flag)
- {
- // Check if there are clips.
- if ((clipSettingsArraySize != 0) || (transitionSettingsArraySize != 0))
- {
- // The number of transitions must be equal to the number of clips - 1.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (clipSettingsArraySize != (transitionSettingsArraySize + 1)),
- "the number of transitions should be equal to the number of clips - 1");
- }
- }
- }
-
- // Only retrieve the EditSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the object is valid.
- if (NULL != object)
- {
- // Allocate memory for the EditSettings.
- pSettings = (M4VSS3GPP_EditSettings*)videoEditOsal_alloc(pResult, pEnv,
- sizeof(M4VSS3GPP_EditSettings), "EditSettings");
-
- // Check if memory could be allocated for the EditSettings.
- if (*pResult)
- {
- // Set the number of clips that will be edited.
- pSettings->uiClipNumber = clipSettingsArraySize;
-
- // Check if the clip settings array contains items.
- if (clipSettingsArraySize > 0)
- {
- // Allocate memory for the clip settings array.
- pSettings->pClipList = (M4VSS3GPP_ClipSettings **)videoEditOsal_alloc(pResult,
- pEnv,
- clipSettingsArraySize * sizeof(M4VSS3GPP_ClipSettings *),
- "ClipSettingsArray");
- if (*pResult)
- {
- // Loop over all clip settings objects.
- for (int i = 0; ((*pResult) && (i < clipSettingsArraySize)); i++)
- {
- // Get the clip settings object.
- clipSettings = pEnv->GetObjectArrayElement(clipSettingsArray, i);
-
- // Get the clip settings.
- videoEditClasses_getClipSettings(pResult, pEnv, clipSettings,
- &pSettings->pClipList[i]);
-
- // Free the local references to avoid memory leaks
- pEnv->DeleteLocalRef(clipSettings);
- }
- }
- }
-
- // Check if the transition settings array contains items.
- if (transitionSettingsArraySize > 0)
- {
- // Allocate memory for the transition settings array.
- pSettings->pTransitionList =
- (M4VSS3GPP_TransitionSettings **)videoEditOsal_alloc(pResult,
- pEnv, transitionSettingsArraySize * sizeof(M4VSS3GPP_TransitionSettings *),
- "TransitionSettingsArray");
- if (*pResult)
- {
- // Loop over all transition settings objects.
- for (int i = 0; ((*pResult) && (i < transitionSettingsArraySize)); i++)
- {
- // Get the transition settings object.
- transitionSettings =
- pEnv->GetObjectArrayElement(transitionSettingsArray, i);
-
- // Get the transition settings.
- videoEditClasses_getTransitionSettings(pResult, pEnv,
- transitionSettings, &pSettings->pTransitionList[i]);
-
- // Free the local references to avoid memory leaks
- pEnv->DeleteLocalRef(transitionSettings);
- }
- }
- }
-
- // Check if the effect settings array contains items.
- if (effectSettingsArraySize > 0)
- {
- // Allocate memory for the effect settings array.
- pSettings->Effects = (M4VSS3GPP_EffectSettings*)videoEditOsal_alloc(pResult,
- pEnv,
- effectSettingsArraySize * sizeof(M4VSS3GPP_EffectSettings),
- "EffectSettingsArray");
- if (*pResult)
- {
- // Loop over all effect settings objects.
- for (int i = 0; ((*pResult) && (i < effectSettingsArraySize)); i++)
- {
- // Get the effect settings object.
- effectSettings = pEnv->GetObjectArrayElement(effectSettingsArray, i);
-
- // Get the effect settings.
- videoEditClasses_getEffectSettings(pResult, pEnv, effectSettings,
- &pSettings->Effects[i]);
-
- // Free the local references to avoid memory leaks
- pEnv->DeleteLocalRef(effectSettings);
- }
- }
- }
-
- // Check if the clips, transitions and effects could be set.
- if (*pResult)
- {
- // Set the number of effects in the clip.
- pSettings->nbEffects = (M4OSA_UInt8)effectSettingsArraySize;
-
- // Set the frame rate of the output video.
- pSettings->videoFrameRate =
- (M4VIDEOEDITING_VideoFramerate)videoEditJava_getVideoFrameRateJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.videoFrameRate));
-
- // Check if the frame rate is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "editSettings.videoFrameRate is invalid");
- }
-
- // Check if the frame rate could be set.
- if (*pResult)
- {
- // Set the path of the output file.
- pSettings->pOutputFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
- object, fieldIds.outputFile, &pSettings->uiOutputPathSize);
- }
-
- // Check if path of the output file could be set.
- if (*pResult)
- {
- // Set the path of the temporary file produced when using
- // the constant memory 3gp writer.
- pSettings->pTemporaryFile = M4OSA_NULL;
-
- // Set the output video size.
- pSettings->xVSS.outputVideoSize =
- (M4VIDEOEDITING_VideoFrameSize)videoEditJava_getVideoFrameSizeJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.videoFrameSize));
-
- // Check if the output video size is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "editSettings.videoFrameSize is invalid");
- }
-
- // Check if the output video size could be set.
- if (*pResult)
- {
- // Set the output video format.
- pSettings->xVSS.outputVideoFormat =
- (M4VIDEOEDITING_VideoFormat)videoEditJava_getVideoFormatJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.videoFormat));
-
- // Check if the output video format is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "editSettings.videoFormat is invalid");
- }
-
- // Check if the output video format could be set.
- if (*pResult)
- {
- // Set the output audio format.
- pSettings->xVSS.outputAudioFormat =
- (M4VIDEOEDITING_AudioFormat)videoEditJava_getAudioFormatJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.audioFormat));
-
- // Check if the output audio format is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "editSettings.audioFormat is invalid");
- }
-
- // Check if the output audio format could be set.
- if (*pResult)
- {
- // Set the output audio sampling frequency when not replacing the audio,
- // or replacing it with MP3 audio.
- pSettings->xVSS.outputAudioSamplFreq =
- (M4VIDEOEDITING_AudioSamplingFrequency)\
- videoEditJava_getAudioSamplingFrequencyJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.audioSamplingFreq));
-
- // Check if the output audio sampling frequency is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "editSettings.audioSamplingFreq is invalid");
- }
-
- // Check if the output audio sampling frequency could be set.
- if (*pResult)
- {
- // Check if the number of audio channels is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- ((0 != audioChannels ) ||
- ((M4VIDEOEDITING_kNoneAudio != pSettings->xVSS.outputAudioFormat) &&
- (M4VIDEOEDITING_kNullAudio != pSettings->xVSS.outputAudioFormat) ) ) &&
- (1 != audioChannels ) &&
- (2 != audioChannels ),
- "editSettings.audioChannels must be set to 0, 1 or 2");
- }
-
- // Check if the number of audio channels is valid.
- if (*pResult)
- {
- // Set the maximum output file size (MMS usecase).
- pSettings->xVSS.outputFileSize = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.maxFileSize);
-
- // Whether or not the audio is mono, only valid for AAC.
- pSettings->xVSS.bAudioMono = (M4OSA_Bool)(1 == audioChannels);
-
- // Set the output video bitrate.
- pSettings->xVSS.outputVideoBitrate = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.videoBitrate);
-
- // Set the output video profile.
- pSettings->xVSS.outputVideoProfile = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.videoProfile);
-
- // Set the output video level.
- pSettings->xVSS.outputVideoLevel = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.videoLevel);
-
- // Set the output audio bitrate.
- pSettings->xVSS.outputAudioBitrate = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.audioBitrate);
-
- // Set the background music settings.
- videoEditClasses_getBackgroundMusicSettings(pResult, pEnv,
- backgroundMusicSettings, &pSettings->xVSS.pBGMtrack);
-
- // Set the text rendering function (will be set elsewhere).
- pSettings->xVSS.pTextRenderingFct = M4OSA_NULL;
- pSettings->PTVolLevel =
- (M4OSA_Float)pEnv->GetIntField(object, fieldIds.primaryTrackVolume);
- }
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeEditSettings(&pSettings);
- }
- }
- }
-}
-
-void
-videoEditClasses_freeEditSettings(
- M4VSS3GPP_EditSettings** ppSettings)
-{
- // Check if memory was allocated for the EditSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeEditSettings()");
-
- // Free the background music settings.
- videoEditClasses_freeBackgroundMusicSettings(&(*ppSettings)->xVSS.pBGMtrack);
-
- // Free the path of the output file.
- videoEditOsal_free((*ppSettings)->pOutputFile);
- (*ppSettings)->pOutputFile = M4OSA_NULL;
- (*ppSettings)->uiOutputPathSize = 0;
-
- // Check if the EffectSettings should be freed.
- if (M4OSA_NULL != (*ppSettings)->Effects)
- {
- // Loop over all effect settings.
- for (int i = 0; i < (*ppSettings)->nbEffects; i++)
- {
- // Free the effect settings.
- videoEditClasses_freeEffectSettings(&(*ppSettings)->Effects[i]);
- }
-
- // Free the memory for the effect settings array.
- videoEditOsal_free((*ppSettings)->Effects);
- (*ppSettings)->Effects = M4OSA_NULL;
- }
-
- // Reset the number of effects in the clip.
- (*ppSettings)->nbEffects = 0;
-
- // Check if there are clips.
- if (0 < (*ppSettings)->uiClipNumber)
- {
- // Check if the TransitionSettings should be freed.
- if (M4OSA_NULL != (*ppSettings)->pTransitionList)
- {
- // Loop over all transition settings.
- for (int i = 0; i < ((*ppSettings)->uiClipNumber - 1); i++)
- {
- // Free the transition settings.
- videoEditClasses_freeTransitionSettings(&(*ppSettings)->pTransitionList[i]);
- }
-
- // Free the memory for the transition settings array.
- videoEditOsal_free((*ppSettings)->pTransitionList);
- (*ppSettings)->pTransitionList = M4OSA_NULL;
- }
-
- // Check if the ClipSettings should be freed.
- if (M4OSA_NULL != (*ppSettings)->pClipList)
- {
- // Loop over all clip settings.
- for (int i = 0; i < (*ppSettings)->uiClipNumber; i++)
- {
- // Free the clip settings.
- videoEditClasses_freeClipSettings(&(*ppSettings)->pClipList[i]);
- }
-
- // Free the memory for the clip settings array.
- videoEditOsal_free((*ppSettings)->pClipList);
- (*ppSettings)->pClipList = M4OSA_NULL;
- }
- }
-
- // Reset the number of clips.
- (*ppSettings)->uiClipNumber = 0;
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logEditSettings(
- M4VSS3GPP_EditSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the EditSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiClipNumber: %d", indentation, ' ',
- pSettings->uiClipNumber);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiMasterClip: %d", indentation, ' ',
- pSettings->uiMasterClip);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pClipList: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pClipList) ? " " : "<null>");
- if (M4OSA_NULL != pSettings->pClipList)
- {
- indentation += VIDEOEDIT_LOG_INDENTATION;
- for (int i = 0; i < pSettings->uiClipNumber; i++)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pClipList[%d]:", indentation, ' ',
- i);
- videoEditClasses_logClipSettings(pSettings->pClipList[i],
- indentation + VIDEOEDIT_LOG_INDENTATION);
- }
- indentation -= VIDEOEDIT_LOG_INDENTATION;
- }
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pTransitionList: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pTransitionList) ? " " : "<null>");
- if (M4OSA_NULL != pSettings->pTransitionList)
- {
- indentation += VIDEOEDIT_LOG_INDENTATION;
- for (int i = 0; i < (pSettings->uiClipNumber - 1); i++)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pTransitionList[%d]:", indentation, ' ', i);
- videoEditClasses_logTransitionSettings(pSettings->pTransitionList[i],
- indentation + VIDEOEDIT_LOG_INDENTATION);
- }
- indentation -= VIDEOEDIT_LOG_INDENTATION;
- }
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c Effects: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->Effects) ? " " : "<null>");
- if (M4OSA_NULL != pSettings->Effects)
- {
- indentation += VIDEOEDIT_LOG_INDENTATION;
- for (int i = 0; i < pSettings->nbEffects; i++)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c Effects[%d]:", indentation, ' ', i);
- videoEditClasses_logEffectSettings(&pSettings->Effects[i],
- indentation + VIDEOEDIT_LOG_INDENTATION);
- }
- indentation -= VIDEOEDIT_LOG_INDENTATION;
- }
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c nbEffects: %d", indentation, ' ',
- pSettings->nbEffects);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c videoFrameRate: %s", indentation, ' ',
- videoEditJava_getVideoFrameRateString(pSettings->videoFrameRate));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pOutputFile: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pOutputFile) ? (char*)pSettings->pOutputFile : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiOutputPathSize: %u", indentation, ' ',
- (unsigned int)pSettings->uiOutputPathSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pTemporaryFile: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pTemporaryFile) ?\
- (char*)pSettings->pTemporaryFile : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputVideoSize: %s", indentation, ' ',
- videoEditJava_getVideoFrameSizeString(pSettings->xVSS.outputVideoSize));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputVideoFormat: %s", indentation, ' ',
- videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoFormat));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputVideoProfile: %u", indentation, ' ',
- videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoProfile));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputVideoLevel: %u", indentation, ' ',
- videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoLevel));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputAudioFormat: %s", indentation, ' ',
- videoEditJava_getAudioFormatString(pSettings->xVSS.outputAudioFormat));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputAudioSamplFreq: %s", indentation, ' ',
- videoEditJava_getAudioSamplingFrequencyString(pSettings->xVSS.outputAudioSamplFreq));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputFileSize: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.outputFileSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bAudioMono: %s", indentation, ' ',
- pSettings->xVSS.bAudioMono ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputVideoBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pSettings->xVSS.outputVideoBitrate));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c outputAudioBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pSettings->xVSS.outputAudioBitrate));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pBGMtrack:", indentation, ' ');
- videoEditClasses_logBackgroundMusicSettings(pSettings->xVSS.pBGMtrack,
- indentation + VIDEOEDIT_LOG_INDENTATION);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pTextRenderingFct: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->xVSS.pTextRenderingFct) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c PTVolLevel: %u", indentation, ' ',
- (unsigned int)pSettings->PTVolLevel);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_getEffectSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_EffectSettings* pSettings)
-{
-
- VideoEditJava_EffectSettingsFieldIds fieldIds;
- bool converted = true;
- memset(&fieldIds, 0, sizeof(VideoEditJava_EffectSettingsFieldIds));
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getEffectSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getEffectSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only validate the EffectSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the effect is set.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (NULL == object),
- "effect is null");
- }
-
- // Only retrieve the EffectSettings if the fields could be located and validated.
- if (*pResult)
- {
- // Set the start time in milliseconds.
- pSettings->uiStartTime = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.startTime);
-
- // Set the duration in milliseconds.
- pSettings->uiDuration = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.duration);
-
- // Set the video effect type, None, FadeIn, FadeOut, etc.
- pSettings->VideoEffectType =
- (M4VSS3GPP_VideoEffectType)videoEditJava_getVideoEffectJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.videoEffectType));
-
- // Check if the video effect type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "effect.videoEffectType is invalid");
- }
-
- // Check if the video effect type could be set.
- if (*pResult)
- {
- // Set the external effect function.
- pSettings->ExtVideoEffectFct = M4OSA_NULL;
-
- // Set the context given to the external effect function.
- pSettings->pExtVideoEffectFctCtxt = M4OSA_NULL;
-
- // Set the audio effect type, None, FadeIn, FadeOut.
- pSettings->AudioEffectType =
- (M4VSS3GPP_AudioEffectType)videoEditJava_getAudioEffectJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.audioEffectType));
-
- // Check if the audio effect type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "effect.audioEffectType is invalid");
- }
-
- // Check if the audio effect type could be set.
- if (*pResult)
- {
- // Set the start in percentage of the cut clip duration.
- pSettings->xVSS.uiStartPercent = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.startPercent);
-
- // Set the duration in percentage of the ((clip duration) - (effect starttime)).
- pSettings->xVSS.uiDurationPercent = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.durationPercent);
-
- // Set the framing file path (GIF/PNG file).
- pSettings->xVSS.pFramingFilePath = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
- object, fieldIds.framingFile, M4OSA_NULL);
-
- // Check if this is a framing effect.
- if (M4xVSS_kVideoEffectType_Framing == (M4xVSS_VideoEffectType)pSettings->VideoEffectType)
- {
- // Check if the framing file path is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (M4OSA_NULL == pSettings->xVSS.pFramingFilePath), "effect.framingFile is null");
- }
- }
-
- // Check if the framing file path could be retrieved.
- if (*pResult)
- {
- // Set the Framing RGB565 buffer.
- pSettings->xVSS.pFramingBuffer = M4OSA_NULL;
-
- // Set the top-left X coordinate in the output picture
- // where the added frame will be displayed.
- pSettings->xVSS.topleft_x = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.topLeftX);
-
- // Set the top-left Y coordinate in the output picture
- // where the added frame will be displayed.
- pSettings->xVSS.topleft_y = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.topLeftY);
-
- // Set whether or not the framing image is resized to output video size.
- pSettings->xVSS.bResize =
- (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.framingResize);
-
- // Set the new size to which framing buffer needs to be resized to
- pSettings->xVSS.framingScaledSize =
- (M4VIDEOEDITING_VideoFrameSize)pEnv->GetIntField(object, fieldIds.framingScaledSize);
-
- // Set the text buffer.
- pSettings->xVSS.pTextBuffer = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
- fieldIds.text, &pSettings->xVSS.textBufferSize);
- }
-
- // Check if the text buffer could be retrieved.
- if (*pResult)
- {
- // Set the data used by the font engine (size, color...).
- pSettings->xVSS.pRenderingData = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
- object, fieldIds.textRenderingData, M4OSA_NULL);
- }
-
- // Check if the text rendering data could be retrieved.
- if (*pResult)
- {
- // Set the text plane width.
- pSettings->xVSS.uiTextBufferWidth = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.textBufferWidth);
-
- // Set the text plane height.
- pSettings->xVSS.uiTextBufferHeight = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.textBufferHeight);
-
- // Set the processing rate of the effect added when using the Fifties effect.
- pSettings->xVSS.uiFiftiesOutFrameRate = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.fiftiesFrameRate);
-
- // Set the RGB16 input color of the effect added when using the rgb16 color effect.
- pSettings->xVSS.uiRgb16InputColor = (M4OSA_UInt16)pEnv->GetIntField(object,
- fieldIds.rgb16InputColor);
-
- // Set the start percentage of Alpha blending.
- pSettings->xVSS.uialphaBlendingStart = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.alphaBlendingStartPercent);
-
- // Set the middle percentage of Alpha blending.
- pSettings->xVSS.uialphaBlendingMiddle = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.alphaBlendingMiddlePercent);
-
- // Set the end percentage of Alpha blending.
- pSettings->xVSS.uialphaBlendingEnd = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.alphaBlendingEndPercent);
-
- // Set the duration, in percentage of effect duration, of the FadeIn phase.
- pSettings->xVSS.uialphaBlendingFadeInTime = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.alphaBlendingFadeInTimePercent);
-
- // Set the duration, in percentage of effect duration, of the FadeOut phase.
- pSettings->xVSS.uialphaBlendingFadeOutTime = (M4OSA_UInt8)pEnv->GetIntField(object,
- fieldIds.alphaBlendingFadeOutTimePercent);
-
- if (pSettings->xVSS.pFramingFilePath != M4OSA_NULL)
- {
- pSettings->xVSS.pFramingBuffer =
- (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(sizeof(M4VIFI_ImagePlane),
- 0x00,(M4OSA_Char *)"framing buffer");
- }
-
- if (pSettings->xVSS.pFramingBuffer != M4OSA_NULL)
- {
- // OverFrame height and width
- pSettings->xVSS.pFramingBuffer->u_width = pEnv->GetIntField(object,
- fieldIds.width);
-
- pSettings->xVSS.pFramingBuffer->u_height = pEnv->GetIntField(object,
- fieldIds.height);
-
- pSettings->xVSS.width = pSettings->xVSS.pFramingBuffer->u_width;
- pSettings->xVSS.height = pSettings->xVSS.pFramingBuffer->u_height;
- pSettings->xVSS.rgbType = M4VSS3GPP_kRGB565;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "pFramingBuffer u_width %d ", pSettings->xVSS.pFramingBuffer->u_width);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "pFramingBuffer u_height %d", pSettings->xVSS.pFramingBuffer->u_height);
-
- }
-
- // Check if settings could be set.
- if (!(*pResult))
- {
- // Free the settings.
- videoEditClasses_freeEffectSettings(pSettings);
- }
- }
-}
-
-void
-videoEditClasses_freeEffectSettings(
- M4VSS3GPP_EffectSettings* pSettings)
-{
- // Check if memory was allocated for the EffectSettings.
- if (M4OSA_NULL != pSettings)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeEffectSettings()");
-
- // Free the data used by the font engine (size, color...).
- videoEditOsal_free(pSettings->xVSS.pRenderingData);
- pSettings->xVSS.pRenderingData = M4OSA_NULL;
-
- // Free the text buffer.
- videoEditOsal_free(pSettings->xVSS.pTextBuffer);
- pSettings->xVSS.pTextBuffer = M4OSA_NULL;
- pSettings->xVSS.textBufferSize = 0;
-
- // Free the framing file path.
- videoEditOsal_free(pSettings->xVSS.pFramingFilePath);
- pSettings->xVSS.pFramingFilePath = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logEffectSettings(
- M4VSS3GPP_EffectSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the EffectSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiStartTime: %u ms", indentation, ' ',
- (unsigned int)pSettings->uiStartTime);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiDuration: %u ms", indentation, ' ',
- (unsigned int)pSettings->uiDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c VideoEffectType: %s", indentation, ' ',
- videoEditJava_getVideoEffectString(pSettings->VideoEffectType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c ExtVideoEffectFct: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->ExtVideoEffectFct) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pExtVideoEffectFctCtxt: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pExtVideoEffectFctCtxt) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c AudioEffectType: %s", indentation, ' ',
- videoEditJava_getAudioEffectString(pSettings->AudioEffectType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiStartPercent: %u %%", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiStartPercent);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiDurationPercent: %u %%", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiDurationPercent);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pFramingFilePath: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->xVSS.pFramingFilePath) ?\
- (char*)pSettings->xVSS.pFramingFilePath : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pFramingBuffer: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->xVSS.pFramingBuffer) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c topleft_x: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.topleft_x);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c topleft_y: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.topleft_y);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c bResize: %s", indentation, ' ',
- pSettings->xVSS.bResize ? "true" : "false");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pTextBuffer: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->xVSS.pTextBuffer) ?\
- (char*)pSettings->xVSS.pTextBuffer : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c textBufferSize: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.textBufferSize);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pRenderingData: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->xVSS.pRenderingData) ?\
- (char*)pSettings->xVSS.pRenderingData : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiTextBufferWidth: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiTextBufferWidth);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiTextBufferHeight: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiTextBufferHeight);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiFiftiesOutFrameRate: %u", indentation, ' ',
- (unsigned int)pSettings->xVSS.uiFiftiesOutFrameRate);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiRgb16InputColor: %d", indentation, ' ',
- pSettings->xVSS.uiRgb16InputColor);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uialphaBlendingStart: %d %%", indentation, ' ',
- pSettings->xVSS.uialphaBlendingStart);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uialphaBlendingMiddle: %d %%", indentation, ' ',
- pSettings->xVSS.uialphaBlendingMiddle);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uialphaBlendingEnd: %d %%", indentation, ' ',
- pSettings->xVSS.uialphaBlendingEnd);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uialphaBlendingFadeInTime: %d %%", indentation, ' ',
- pSettings->xVSS.uialphaBlendingFadeInTime);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uialphaBlendingFadeOutTime: %d %%", indentation, ' ',
- pSettings->xVSS.uialphaBlendingFadeOutTime);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_getSlideTransitionSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_SlideTransitionSettings** ppSettings)
-{
- VideoEditJava_SlideTransitionSettingsFieldIds fieldIds = {NULL};
- M4xVSS_SlideTransitionSettings* pSettings = M4OSA_NULL;
- bool converted = true;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getSlideTransitionSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getSlideTransitionSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
-
- // Only validate the SlideTransitionSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the clip is set.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (NULL == object),
- "slideSettings is null");
- }
-
- // Only retrieve the SlideTransitionSettings if the fields could be located and validated.
- if (*pResult)
- {
- // Allocate memory for the SlideTransitionSettings.
- pSettings = (M4xVSS_SlideTransitionSettings*)videoEditOsal_alloc(pResult, pEnv,
- sizeof(M4xVSS_SlideTransitionSettings), "SlideTransitionSettings");
-
- // Check if memory could be allocated for the SlideTransitionSettings.
- if (*pResult)
- {
- // Set the direction of the slide.
- pSettings->direction =
- (M4xVSS_SlideTransition_Direction)videoEditJava_getSlideDirectionJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.direction));
-
- // Check if the direction is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- !converted, "slideSettings.direction is invalid");
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeSlideTransitionSettings(&pSettings);
- }
- }
-}
-
-void
-videoEditClasses_freeSlideTransitionSettings(
- M4xVSS_SlideTransitionSettings** ppSettings)
-{
- // Check if memory was allocated for the SlideTransitionSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeSlideTransitionSettings()");
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logSlideTransitionSettings(
- M4xVSS_SlideTransitionSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the SlideTransitionSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c direction: %s", indentation, ' ',
- videoEditJava_getSlideDirectionString(pSettings->direction));
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_getTransitionSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_TransitionSettings** ppSettings)
-{
-
- VideoEditJava_TransitionSettingsFieldIds fieldIds;
- jobject alphaSettings = NULL;
- jobject slideSettings = NULL;
- M4VSS3GPP_TransitionSettings* pSettings = M4OSA_NULL;
- bool converted = true;
- memset(&fieldIds, 0, sizeof(VideoEditJava_TransitionSettingsFieldIds));
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getTransitionSettings()");
-
- // Retrieve the field ids.
- videoEditJava_getTransitionSettingsFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only validate the TransitionSettings if the fields could be located.
- if (*pResult)
- {
- // Check if the transition is set.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (NULL == object),
- "transition is null");
- }
-
- // Check if the field ids could be located and validated.
- if (*pResult)
- {
- // Retrieve the alphaSettings.
- videoEditJava_getObject(pResult, pEnv, object, fieldIds.alphaSettings, &alphaSettings);
-
- // Retrieve the slideSettings.
- videoEditJava_getObject(pResult, pEnv, object, fieldIds.slideSettings, &slideSettings);
- }
-
- // Only retrieve the TransitionSettings if the fields could be located.
- if (*pResult)
- {
- // Allocate memory for the TransitionSettings.
- pSettings = (M4VSS3GPP_TransitionSettings*)videoEditOsal_alloc(pResult,
- pEnv, sizeof(M4VSS3GPP_TransitionSettings), "TransitionSettings");
-
- // Check if memory could be allocated for the TransitionSettings.
- if (*pResult)
- {
- // Set the duration of the transition, in milliseconds (set to 0 to get no transition).
- pSettings->uiTransitionDuration = (M4OSA_UInt32)pEnv->GetIntField(object,
- fieldIds.duration);
-
- // Set the type of the video transition.
- pSettings->VideoTransitionType =
- (M4VSS3GPP_VideoTransitionType)videoEditJava_getVideoTransitionJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.videoTransitionType));
-
- // Check if the video transition type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
- "transition.videoTransitionType is invalid");
- }
-
- // Check if the video transition type could be set.
- if (*pResult)
- {
- // Set the external transition video effect function.
- pSettings->ExtVideoTransitionFct = M4OSA_NULL;
-
- // Set the context of the external transition video effect function.
- pSettings->pExtVideoTransitionFctCtxt = M4OSA_NULL;
-
- // Set the type of the audio transition.
- pSettings->AudioTransitionType =
- (M4VSS3GPP_AudioTransitionType)videoEditJava_getAudioTransitionJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.audioTransitionType));
-
- // Check if the audio transition type is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
- "transition.audioTransitionType is invalid");
- }
-
- // Check if the audio transition type could be set.
- if (*pResult)
- {
- // Set the transition behaviour.
- pSettings->TransitionBehaviour =
- (M4VSS3GPP_TransitionBehaviour)videoEditJava_getTransitionBehaviourJavaToC(
- &converted, pEnv->GetIntField(object, fieldIds.transitionBehaviour));
-
- // Check if the transition behaviour is valid.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
- "transition.transitionBehaviour is invalid");
- }
-
- // Check if the audio transition behaviour could be set.
- if (*pResult)
- {
- // Check if a slide transition or alpha magic setting object is expected.
- if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
- {
- // Set the slide transition settings.
- videoEditClasses_getSlideTransitionSettings(pResult, pEnv, slideSettings,
- &pSettings->xVSS.transitionSpecific.pSlideTransitionSettings);
- }
- else if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_AlphaMagic)
- {
- // Set the alpha magic settings.
- videoEditClasses_getAlphaMagicSettings(pResult, pEnv, alphaSettings,
- &pSettings->xVSS.transitionSpecific.pAlphaMagicSettings);
- }
- }
-
- // Check if settings could be set.
- if (*pResult)
- {
- // Return the settings.
- (*ppSettings) = pSettings;
- }
- else
- {
- // Free the settings.
- videoEditClasses_freeTransitionSettings(&pSettings);
- }
- }
-}
-
-void
-videoEditClasses_freeTransitionSettings(
- M4VSS3GPP_TransitionSettings** ppSettings)
-{
- // Check if memory was allocated for the TransitionSettings.
- if (M4OSA_NULL != (*ppSettings))
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_freeTransitionSettings()");
-
- // Check if a slide transition or alpha magic setting structure is expected.
- if ((int)(*ppSettings)->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
- {
- // Free the slide transition settings.
- videoEditClasses_freeSlideTransitionSettings(
- &(*ppSettings)->xVSS.transitionSpecific.pSlideTransitionSettings);
- }
- else
- {
- // Free the alpha magic settings.
- videoEditClasses_freeAlphaMagicSettings(
- &(*ppSettings)->xVSS.transitionSpecific.pAlphaMagicSettings);
- }
-
- // Free the settings structure.
- videoEditOsal_free((*ppSettings));
- (*ppSettings) = M4OSA_NULL;
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logTransitionSettings(
- M4VSS3GPP_TransitionSettings* pSettings,
- int indentation)
-{
- // Check if memory was allocated for the TransitionSettings.
- if (M4OSA_NULL != pSettings)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c uiTransitionDuration: %u ms", indentation, ' ',
- (unsigned int)pSettings->uiTransitionDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c VideoTransitionType: %s", indentation, ' ',
- videoEditJava_getVideoTransitionString(pSettings->VideoTransitionType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c ExtVideoTransitionFct: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->ExtVideoTransitionFct) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pExtVideoTransitionFctCtxt: %s", indentation, ' ',
- (M4OSA_NULL != pSettings->pExtVideoTransitionFctCtxt) ? "set" : "<null>");
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c AudioTransitionType: %s", indentation, ' ',
- videoEditJava_getAudioTransitionString(pSettings->AudioTransitionType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c TransitionBehaviour: %s", indentation, ' ',
- videoEditJava_getTransitionBehaviourString(pSettings->TransitionBehaviour));
-
- // Check if a slide transition or alpha magic setting structure is expected.
- if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
- {
- // Log the slide transition settings.
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pSlideTransitionSettings:", indentation, ' ');
- videoEditClasses_logSlideTransitionSettings\
- (pSettings->xVSS.transitionSpecific.pSlideTransitionSettings,
- indentation + VIDEOEDIT_LOG_INDENTATION);
- }
- else
- {
- // Log the alpha magic settings.
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c pAlphaMagicSettings:", indentation, ' ');
- videoEditClasses_logAlphaMagicSettings\
- (pSettings->xVSS.transitionSpecific.pAlphaMagicSettings,
- indentation + VIDEOEDIT_LOG_INDENTATION);
- }
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditPropClass_logProperties(
- VideoEditPropClass_Properties* pProperties,
- int indentation)
-{
- // Check if memory was allocated for the Properties.
- if (M4OSA_NULL != pProperties)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiClipDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipDuration);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c FileType: %s", indentation, ' ',
- videoEditJava_getFileTypeString(pProperties->FileType));
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c VideoStreamType: %s", indentation, ' ',
- videoEditJava_getVideoFormatString(pProperties->VideoStreamType));
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiClipVideoDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipVideoDuration);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiVideoBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pProperties->uiVideoBitrate));
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiVideoWidth: %u", indentation, ' ',
- (unsigned int)pProperties->uiVideoWidth);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiVideoHeight: %u", indentation, ' ',
- (unsigned int)(unsigned int)pProperties->uiVideoHeight);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c fAverageFrameRate: %.3f", indentation, ' ',
- pProperties->fAverageFrameRate);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c AudioStreamType: %s", indentation, ' ',
- videoEditJava_getAudioFormatString(pProperties->AudioStreamType));
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiClipAudioDuration: %u", indentation, ' ',
- (unsigned int)pProperties->uiClipAudioDuration);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiAudioBitrate: %s", indentation, ' ',
- videoEditJava_getBitrateString(pProperties->uiAudioBitrate));
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiNbChannels: %u", indentation, ' ',
- (unsigned int)pProperties->uiNbChannels);
-
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c uiSamplingFrequency: %u", indentation, ' ',
- (unsigned int)pProperties->uiSamplingFrequency);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void
-videoEditClasses_createVersion(
- bool* pResult,
- JNIEnv* pEnv,
- M4_VersionInfo* pVersionInfo,
- jobject* pObject)
-{
-
- VideoEditJava_VersionFieldIds fieldIds;
- jclass clazz = NULL;
- jobject object = NULL;
- memset(&fieldIds, 0, sizeof(VideoEditJava_VersionFieldIds));
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_createVersion()");
-
- // Retrieve the class.
- videoEditJava_getVersionClass(pResult, pEnv, &clazz);
-
- // Retrieve the field ids.
- videoEditJava_getVersionFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Only create an object if the class and fields could be located.
- if (*pResult)
- {
- // Allocate a new object.
- object = pEnv->AllocObject(clazz);
-
- // check if alloc is done
- videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
- (NULL == object),
- M4ERR_ALLOC);
- if (NULL != object)
- {
- // Set the major field.
- pEnv->SetIntField(object, fieldIds.major, pVersionInfo->m_major);
-
- // Set the minor field.
- pEnv->SetIntField(object, fieldIds.minor, pVersionInfo->m_minor);
-
- // Set the revision field.
- pEnv->SetIntField(object, fieldIds.revision, pVersionInfo->m_revision);
-
- // Return the object.
- (*pObject) = object;
- }
- }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logVersion(
- M4_VersionInfo* pVersionInfo,
- int indentation)
-{
- // Check if memory was allocated for the Version.
- if (M4OSA_NULL != pVersionInfo)
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c major: %u ms", indentation, ' ',
- (unsigned int)pVersionInfo->m_major);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c minor: %u", indentation, ' ',
- (unsigned int)pVersionInfo->m_minor);
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c revision: %u", indentation, ' ',
- (unsigned int)pVersionInfo->m_revision);
- }
- else
- {
- VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "%*c <null>", indentation, ' ');
- }
-}
-#endif
-
-
-void*
-videoEditClasses_getContext(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object)
-{
- void* pContext = M4OSA_NULL;
- jclass clazz = NULL;
- VideoEditJava_EngineFieldIds fieldIds = {NULL};
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_getContext()");
-
- // Retrieve the class.
- videoEditJava_getEngineClass(pResult, pEnv, &clazz);
-
- // Retrieve the field ids.
- videoEditJava_getEngineFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Check if the class and field ids could be located.
- if (*pResult)
- {
- // Retrieve the context pointer.
- pContext = (void *)pEnv->GetLongField(object, fieldIds.context);
- }
-
- // Return the context pointer.
- return(pContext);
-}
-
-void
-videoEditClasses_setContext(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- void* pContext)
-{
- jclass clazz = NULL;
- VideoEditJava_EngineFieldIds fieldIds = {NULL};
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "videoEditClasses_setContext()");
-
- // Retrieve the class.
- videoEditJava_getEngineClass(pResult, pEnv, &clazz);
-
- // Retrieve the field ids.
- videoEditJava_getEngineFieldIds(pResult, pEnv, &fieldIds);
- }
-
- // Check if the class and field ids could be located.
- if (*pResult)
- {
- // Set the context field.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "The context value from JAVA before setting is = %p",
- (void *)pEnv->GetLongField(object, fieldIds.context));
-
- pEnv->SetLongField(object, fieldIds.context, (jlong)pContext);
- M4OSA_TRACE1_1("The context value in JNI is = %p",pContext);
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
- "The context value from JAVA after setting is = %p",
- (void *)pEnv->GetLongField(object, fieldIds.context));
- }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorClasses.h b/media/jni/mediaeditor/VideoEditorClasses.h
deleted file mode 100644
index a4c82a8..0000000
--- a/media/jni/mediaeditor/VideoEditorClasses.h
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_CLASSES_H
-#define VIDEO_EDITOR_CLASSES_H
-
-#include <VideoEditorJava.h>
-#include <VideoEditorClasses.h>
-/**
- ************************************************************************
- * @file VideoEditorClasses.h
- * @brief Interface for JNI methods/defines that have specific
- * access to class, objects and method Ids defined in Java layer
- ************************************************************************
-*/
-
-
-extern "C" {
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-};
-
-/*
- * Java layer class/object name strings
- */
-#define PACKAGE_NAME "android/media/videoeditor"
-
-#define MANUAL_EDIT_ENGINE_CLASS_NAME PACKAGE_NAME"/MediaArtistNativeHelper"
-#define MEDIA_PROPERTIES_ENGINE_CLASS_NAME PACKAGE_NAME"/MediaArtistNativeHelper"
-
-#define AUDIO_FORMAT_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioFormat"
-#define RESULTS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$Results"
-#define VERSION_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$Version"
-#define AUDIO_SAMPLING_FREQUENCY_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioSamplingFrequency"
-#define BITRATE_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$Bitrate"
-#define ERROR_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$Result"
-#define FILE_TYPE_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$FileType"
-#define MEDIA_RENDERING_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$MediaRendering"
-#define VIDEO_FORMAT_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFormat"
-#define VIDEO_FRAME_RATE_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFrameRate"
-#define VIDEO_FRAME_SIZE_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFrameSize"
-#define VIDEO_PROFILE_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoProfile"
-#define ALPHA_MAGIC_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AlphaMagicSettings"
-#define AUDIO_EFFECT_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioEffect"
-#define AUDIO_TRANSITION_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioTransition"
-#define BACKGROUND_MUSIC_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$BackgroundMusicSettings"
-#define CLIP_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$ClipSettings"
-#define EDIT_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$EditSettings"
-#define EFFECT_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$EffectSettings"
-#define SLIDE_DIRECTION_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$SlideDirection"
-#define SLIDE_TRANSITION_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$SlideTransitionSettings"
-#define TRANSITION_BEHAVIOUR_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$TransitionBehaviour"
-#define TRANSITION_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$TransitionSettings"
-#define VIDEO_EFFECT_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoEffect"
-#define VIDEO_TRANSITION_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoTransition"
-#define PREVIEW_CLIPS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewClips"
-#define PREVIEW_SETTING_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewSettings"
-#define PREVIEW_PROPERTIES_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewClipProperties"
-#define AUDIO_SETTINGS_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioSettings"
-#define PROPERTIES_CLASS_NAME MANUAL_EDIT_ENGINE_CLASS_NAME"$Properties"
-
-#define TASK_IDLE 0
-#define TASK_LOADING_SETTINGS 1
-#define TASK_ENCODING 2
-
-/*
- * File type enum
- */
-typedef enum
-{
- VideoEditClasses_kFileType_3GPP,
- VideoEditClasses_kFileType_MP4,
- VideoEditClasses_kFileType_AMR,
- VideoEditClasses_kFileType_MP3,
- VideoEditClasses_kFileType_PCM,
- VideoEditClasses_kFileType_JPG,
- VideoEditClasses_kFileType_BMP,
- VideoEditClasses_kFileType_GIF,
- VideoEditClasses_kFileType_PNG,
- VideoEditClasses_kFileType_ARGB8888,
- VideoEditClasses_kFileType_M4V,
- VideoEditClasses_kFileType_Unsupported
-} VideoEditClasses_FileType;
-
-/*
- * Alpha magic transition structure
- */
-typedef struct
-{
- jfieldID file;
- jfieldID blendingPercent;
- jfieldID invertRotation;
- jfieldID rgbWidth;
- jfieldID rgbHeight;
-} VideoEditJava_AlphaMagicFieldIds;
-
-typedef struct
-{
- jfieldID file;
- jfieldID fileType;
- jfieldID insertionTime;
- jfieldID volumePercent;
- jfieldID beginLoop;
- jfieldID endLoop;
- jfieldID enableDucking;
- jfieldID duckingThreshold;
- jfieldID lowVolume;
- jfieldID isLooping;
-} VideoEditJava_BackgroundMusicFieldIds;
-/*
- * Structure to hold media properties from native layer
- */
-typedef struct {
- M4OSA_UInt32 uiClipDuration;
- VideoEditClasses_FileType FileType;
- M4VIDEOEDITING_VideoFormat VideoStreamType;
- M4OSA_UInt32 uiClipVideoDuration;
- M4OSA_UInt32 uiVideoBitrate;
- M4OSA_UInt32 uiVideoWidth;
- M4OSA_UInt32 uiVideoHeight;
- M4OSA_Float fAverageFrameRate;
- M4OSA_UInt32 uiVideoProfile; /**< H263 or MPEG-4 or H264 profile(from core decoder) */
- M4OSA_UInt32 uiVideoLevel; /**< H263 or MPEG-4 or H264 level*/
- M4OSA_Bool bProfileSupported;
- M4OSA_Bool bLevelSupported;
- M4VIDEOEDITING_AudioFormat AudioStreamType;
- M4OSA_UInt32 uiClipAudioDuration;
- M4OSA_UInt32 uiAudioBitrate;
- M4OSA_UInt32 uiNbChannels;
- M4OSA_UInt32 uiSamplingFrequency;
- M4OSA_UInt32 uiRotation;
-} VideoEditPropClass_Properties;
-
-typedef struct
-{
- jfieldID duration;
- jfieldID fileType;
- jfieldID videoFormat;
- jfieldID videoDuration;
- jfieldID videoBitrate;
- jfieldID width;
- jfieldID height;
- jfieldID averageFrameRate;
- jfieldID profile;
- jfieldID level;
- jfieldID profileSupported;
- jfieldID levelSupported;
- jfieldID audioFormat;
- jfieldID audioDuration;
- jfieldID audioBitrate;
- jfieldID audioChannels;
- jfieldID audioSamplingFrequency;
- jfieldID videoRotation;
-} VideoEditJava_PropertiesFieldIds;
-
-
-typedef struct
-{
- jfieldID clipPath;
- jfieldID fileType;
- jfieldID beginCutTime;
- jfieldID endCutTime;
- jfieldID beginCutPercent;
- jfieldID endCutPercent;
- jfieldID panZoomEnabled;
- jfieldID panZoomPercentStart;
- jfieldID panZoomTopLeftXStart;
- jfieldID panZoomTopLeftYStart;
- jfieldID panZoomPercentEnd;
- jfieldID panZoomTopLeftXEnd;
- jfieldID panZoomTopLeftYEnd;
- jfieldID mediaRendering;
- jfieldID rgbFileWidth;
- jfieldID rgbFileHeight;
- jfieldID rotationDegree;
-} VideoEditJava_ClipSettingsFieldIds;
-
-typedef struct
-{
- jfieldID clipSettingsArray;
- jfieldID transitionSettingsArray;
- jfieldID effectSettingsArray;
- jfieldID videoFrameRate;
- jfieldID outputFile;
- jfieldID videoFrameSize;
- jfieldID videoFormat;
- jfieldID videoProfile;
- jfieldID videoLevel;
- jfieldID audioFormat;
- jfieldID audioSamplingFreq;
- jfieldID maxFileSize;
- jfieldID audioChannels;
- jfieldID videoBitrate;
- jfieldID audioBitrate;
- jfieldID backgroundMusicSettings;
- jfieldID primaryTrackVolume;
-} VideoEditJava_EditSettingsFieldIds;
-
-
-typedef struct
-{
- jfieldID startTime;
- jfieldID duration;
- jfieldID videoEffectType;
- jfieldID audioEffectType;
- jfieldID startPercent;
- jfieldID durationPercent;
- jfieldID framingFile;
- jfieldID framingBuffer;
- jfieldID bitmapType;
- jfieldID width;
- jfieldID height;
- jfieldID topLeftX;
- jfieldID topLeftY;
- jfieldID framingResize;
- jfieldID framingScaledSize;
- jfieldID text;
- jfieldID textRenderingData;
- jfieldID textBufferWidth;
- jfieldID textBufferHeight;
- jfieldID fiftiesFrameRate;
- jfieldID rgb16InputColor;
- jfieldID alphaBlendingStartPercent;
- jfieldID alphaBlendingMiddlePercent;
- jfieldID alphaBlendingEndPercent;
- jfieldID alphaBlendingFadeInTimePercent;
- jfieldID alphaBlendingFadeOutTimePercent;
-} VideoEditJava_EffectSettingsFieldIds;
-
-typedef struct
-{
- jfieldID context;
-} VideoEditJava_EngineFieldIds;
-
-typedef struct
-{
- jfieldID direction;
-} VideoEditJava_SlideTransitionSettingsFieldIds;
-
-typedef struct
-{
- jfieldID duration;
- jfieldID videoTransitionType;
- jfieldID audioTransitionType;
- jfieldID transitionBehaviour;
- jfieldID alphaSettings;
- jfieldID slideSettings;
-} VideoEditJava_TransitionSettingsFieldIds;
-
-typedef struct
-{
- jfieldID major;
- jfieldID minor;
- jfieldID revision;
-} VideoEditJava_VersionFieldIds;
-
-
-typedef struct
-{
- jmethodID onProgressUpdate;
-} VideoEditJava_EngineMethodIds;
-
-
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioEffect )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioFormat )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioSamplingFrequency)
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioTransition )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Bitrate )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Engine )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Error )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(FileType )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(MediaRendering )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(SlideDirection )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(TransitionBehaviour )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoEffect )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFormat )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFrameRate )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFrameSize )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoProfile )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoTransition )
-
-
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(AlphaMagic )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(BackgroundMusic )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(ClipSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(ClipSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(EditSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(EffectSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(Engine )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(SlideTransitionSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(TransitionSettings )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(Version )
-
-VIDEOEDIT_JAVA_DECLARE_METHOD_CLASS(Engine )
-
-/*
- * Init all Edit settings related structures
- */
-void
-videoEditClasses_init(
- bool* pResult,
- JNIEnv* pEnv);
-/**
- ************************************************************************
- * @brief Media Properties init function.
- * @param pResult (OUT) Pointer to hold result
- * @param pEnv (IN) JVM Interface pointer
- ************************************************************************
-*/
-void
-videoEditPropClass_init(
- bool* pResult,
- JNIEnv* pEnv);
-/**
- ************************************************************************
- * @brief Interface to populate Media Properties.
- * @param pResult (IN/OUT) Pointer to hold result
- * @param pEnv (IN) JVM Interface pointer
- * @param pProperties (IN) Media propeties structure pointer
- * @param pObject (OUT) Java object to hold media
- * properties for java layer.
- ************************************************************************
-*/
-void
-videoEditPropClass_createProperties(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditPropClass_Properties* pProperties,
- jobject* pObject);
-
-/**
- ************************************************************************
- * @brief Interface to log/display media properties.
- * @param pProperties (IN) Pointer holding media properties
- * @param indentation (IN) Indentation to follow in display
- ************************************************************************
-*/
-void
-videoEditPropClass_logProperties(
- VideoEditPropClass_Properties* pProperties,
- int indentation);
-
-/*
- * Get alpha magic transition settings
- */
-void
-videoEditClasses_getAlphaMagicSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_AlphaMagicSettings** ppSettings);
-
-/*
- * Free alpha magic transition settings structure
- */
-void
-videoEditClasses_freeAlphaMagicSettings(
- M4xVSS_AlphaMagicSettings** ppSettings);
-
-/*
- * Log alpha magic transition settings
- */
-void
-videoEditClasses_logAlphaMagicSettings(
- M4xVSS_AlphaMagicSettings* pSettings,
- int indentation);
-
-/*
- * Get Background Track settings
- */
-void
-videoEditClasses_getBackgroundMusicSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_BGMSettings** ppSettings);
-
-/*
- * Free Background Track settings structure
- */
-void
-videoEditClasses_freeBackgroundMusicSettings(
- M4xVSS_BGMSettings** ppSettings);
-
-/*
- * Log Background Track settings
- */
-void
-videoEditClasses_logBackgroundMusicSettings(
- M4xVSS_BGMSettings* pSettings,
- int indentation);
-
-/*
- * Log clip properties
- */
-void
-videoEditClasses_logClipProperties(
- M4VIDEOEDITING_ClipProperties* pProperties,
- int indentation);
-
-/*
- * Get clip settings from Java
- */
-void
-videoEditClasses_getClipSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_ClipSettings** ppSettings);
-/**
- ************************************************************************
- * @brief Interface function to retrieve media properties for a given
- * file.
- * @param pEnv (IN) Pointer holding media properties
- * @param thiz (IN) Indentation to follow in display
- * @param file (IN) File path for which media properties has
- * to be retrieved.
- ************************************************************************
-*/
-jobject
-videoEditProp_getProperties(
- JNIEnv* pEnv,
- jobject thiz,
- jstring file);
-
-/*
- * Create/Set the clip settings to java Object
- */
-void
-videoEditClasses_createClipSettings(
- bool* pResult,
- JNIEnv* pEnv,
- M4VSS3GPP_ClipSettings* pSettings,
- jobject* pObject);
-
-/*
- * Free clip settings structure
- */
-void
-videoEditClasses_freeClipSettings(
- M4VSS3GPP_ClipSettings** ppSettings);
-
-/*
- * Log clip settings structure
- */
-void
-videoEditClasses_logClipSettings(
- M4VSS3GPP_ClipSettings* pSettings,
- int indentation);
-
-/*
- * Get Edit settings from Java
- */
-void
-videoEditClasses_getEditSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_EditSettings** ppSettings,
- bool flag);
-
-/*
- * Free Edit Settings structure
- */
-void
-videoEditClasses_freeEditSettings(
- M4VSS3GPP_EditSettings** ppSettings);
-
-/*
- * Log Edit settings structure
- */
-void
-videoEditClasses_logEditSettings(
- M4VSS3GPP_EditSettings* pSettings,
- int indentation);
-
-/*
- * Get Effect settings from Java
- */
-void
-videoEditClasses_getEffectSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_EffectSettings* pSettings);
-
-/*
- * Free Effect settings structure
- */
-void
-videoEditClasses_freeEffectSettings(
- M4VSS3GPP_EffectSettings* pSettings);
-
-/*
- * Log Effect settings
- */
-void
-videoEditClasses_logEffectSettings(
- M4VSS3GPP_EffectSettings* pSettings,
- int indentation);
-
-/*
- * Get Transition-Sliding settings from Java
- */
-void
-videoEditClasses_getSlideTransitionSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4xVSS_SlideTransitionSettings** ppSettings);
-
-/*
- * Free Transition-Sliding structure
- */
-void
-videoEditClasses_freeSlideTransitionSettings(
- M4xVSS_SlideTransitionSettings** ppSettings);
-
-/*
- * Free Transition-Sliding structure
- */
-void
-videoEditClasses_logSlideTransitionSettings(
- M4xVSS_SlideTransitionSettings* pSettings,
- int indentation);
-
-/*
- * Get Transition settings from Java
- */
-void
-videoEditClasses_getTransitionSettings(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_TransitionSettings** ppSettings);
-
-/*
- * Free Transition settings structure
- */
-void
-videoEditClasses_freeTransitionSettings(
- M4VSS3GPP_TransitionSettings** ppSettings);
-
-/*
- * Log Transition settings
- */
-void
-videoEditClasses_logTransitionSettings(
- M4VSS3GPP_TransitionSettings* pSettings,
- int indentation);
-
-/*
- * Set version information to Java object
- */
-void
-videoEditClasses_createVersion(
- bool* pResult,
- JNIEnv* pEnv,
- M4_VersionInfo* pVersionInfo,
- jobject* pObject);
-
-/*
- * Log Version information
- */
-void
-videoEditClasses_logVersion(
- M4_VersionInfo* pVersionInfo,
- int indentation);
-
-
-void*
-videoEditClasses_getContext(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object);
-
-void
-videoEditClasses_setContext(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- void* pContext);
-
-
-#endif // VIDEO_EDITOR_CLASSES_H
-
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
deleted file mode 100644
index fde0fb5..0000000
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ /dev/null
@@ -1,901 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorJava"
-
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_CharStar.h>
-};
-
-
-void
-videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- const char* pMessage,
- const char* pFile,
- int lineNo)
-{
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the condition is true.
- if (condition)
- {
- // Log the exception.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",\
- "videoEditJava_checkAndThrowIllegalArgumentException, %s (%s:%d)",
- pMessage, pFile, lineNo);
-
- // Reset the result flag.
- (*pResult) = false;
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/IllegalArgumentException", pMessage);
- }
- }
-}
-
-void
-videoEditJava_checkAndThrowRuntimeExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- M4OSA_ERR result,
- const char* pFile,
- int lineNo
- )
-{
- const char* pMessage = NULL;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the condition is true.
- if (condition)
- {
- // Get the error string.
- pMessage = videoEditJava_getErrorName(result);
-
- // Log the exception.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_checkAndThrowRuntimeException, %s (%s:%d)",
- pMessage, pFile, lineNo);
-
- // Reset the result flag.
- (*pResult) = false;
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
- }
- }
-}
-
-void
-videoEditJava_checkAndThrowIllegalStateExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- const char* pMessage,
- const char* pFile,
- int lineNo
- )
-{
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the condition is true.
- if (condition)
- {
- // Log the exception.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_checkAndThrowIllegalStateException, %s (%s:%d)",
- pMessage, pFile, lineNo);
-
- // Reset the result flag.
- (*pResult) = false;
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/IllegalStateException", pMessage);
- }
- }
-}
-
-void
-videoEditJava_getClass(
- bool* pResult,
- JNIEnv* pEnv,
- const char* pName,
- jclass* pClazz)
-{
- // Only look for the class if locating the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getClass(%s)", pName);
-
- // Look up the class.
- jclass clazz = pEnv->FindClass(pName);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the class could be located.
- if (NULL != clazz)
- {
- // Return the class.
- (*pClazz) = clazz;
- }
- else
- {
- // Reset the result flag.
- (*pResult) = false;
-
- // Log the error.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getClass, error: unable to locate class %s", pName);
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/ClassNotFoundException",
- "unable to locate class");
- }
- }
-}
-
-void
-videoEditJava_getMethodId(
- bool* pResult,
- JNIEnv* pEnv,
- jclass clazz,
- const char* pName,
- const char* pType,
- jmethodID* pMethodId)
-{
- // Only look for the class if locating the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getMethodId(%s,%s)", pName, pType);
-
- // Look up the method id.
- jmethodID methodId = pEnv->GetMethodID(clazz, pName, pType);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the method could be located.
- if (NULL != methodId)
- {
- // Return the method id.
- (*pMethodId) = methodId;
- }
- else
- {
- // Reset the result flag.
- (*pResult) = false;
-
- // Log the error.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getMethodId, error: unable to locate method %s with type %s",
- pName, pType);
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/NoSuchMethodException", "unable to locate method");
- }
- }
-}
-
-void
-videoEditJava_getFieldId(
- bool* pResult,
- JNIEnv* pEnv,
- jclass clazz,
- const char* pName,
- const char* pType,
- jfieldID* pFieldId)
-{
- // Only look for the class if locating the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getFieldId(%s,%s)", pName, pType);
-
- // Look up the field id.
- jfieldID fieldId = pEnv->GetFieldID(clazz, pName, pType);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the field could be located.
- if (NULL != fieldId)
- {
- // Return the field id.
- (*pFieldId) = fieldId;
- }
- else
- {
- // Reset the result flag.
- (*pResult) = false;
-
- // Log the error.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getFieldId, error: unable to locate field %s with type %s",
- pName, pType);
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/NoSuchFieldException", "unable to locate field");
- }
- }
-}
-
-void
-videoEditJava_getObject(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID objectFieldId,
- jobject* pObject)
-{
- // Only retrieve the array object and size if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getObject()");
-
- // Retrieve the object.
- (*pObject) = pEnv->GetObjectField(object, objectFieldId);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
- }
-}
-
-void
-videoEditJava_getArray(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID arrayFieldId,
- jobjectArray* pArray,
- jsize* pArraySize)
-{
- // Only retrieve the array object and size if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getArray()");
-
- // Retrieve the array object.
- jobjectArray array = (jobjectArray)pEnv->GetObjectField(object, arrayFieldId);
- jsize arraySize = 0;
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the array could be retrieved.
- if (NULL != array)
- {
- // Retrieve the array size.
- arraySize = pEnv->GetArrayLength(array);
- }
-
- // Return the array and its size.
- (*pArray) = array;
- (*pArraySize) = arraySize;
- }
-}
-
-void*
-videoEditJava_getString(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID stringFieldId,
- M4OSA_UInt32* pLength)
-{
- void* pString = M4OSA_NULL;
- jstring string = NULL;
- M4OSA_UInt32 length = 0;
- M4OSA_Char* pLocal = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getString()");
-
- // Check if an object containing a string was specified.
- if (NULL != stringFieldId)
- {
- // Retrieve the string object.
- string = (jstring)pEnv->GetObjectField(object, stringFieldId);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
- }
- else
- {
- // The string itself was specified.
- string = (jstring)object;
- }
-
- // Check if the string could be retrieved.
- if (NULL != string)
- {
- // Get a local copy of the string.
- pLocal = (M4OSA_Char*)pEnv->GetStringUTFChars(string, M4OSA_NULL);
- if (M4OSA_NULL != pLocal)
- {
- // Determine the length of the path
- // (add one extra character for the zero terminator).
- length = strlen((const char *)pLocal) + 1;
-
- // Allocate memory for the string.
- pString = videoEditOsal_alloc(pResult, pEnv, length, "String");
- if (*pResult)
- {
- // Copy the string.
- result = M4OSA_chrNCopy((M4OSA_Char*)pString, pLocal, length);
-
- // Check if the copy succeeded.
- videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
- (M4NO_ERROR != result), result);
-
- // Check if the string could not be copied.
- if (!(*pResult))
- {
- // Free the allocated memory.
- videoEditOsal_free(pString);
- pString = M4OSA_NULL;
- }
- }
-
- // Release the local copy of the string.
- pEnv->ReleaseStringUTFChars(string, (const char *)pLocal);
- }
- }
-
- // Check if the string was empty or could be copied.
- if (*pResult)
- {
- // Check if the length was requested.
- if (M4OSA_NULL != pLength)
- {
- // Return the length.
- (*pLength) = length;
- }
- }
-
- // Delete local references to avoid memory leaks
- pEnv->DeleteLocalRef(string);
- }
-
- // Return the string.
- return(pString);
-}
-
-void
-videoEditJava_getStaticIntField(
- bool* pResult,
- JNIEnv* pEnv,
- jclass clazz,
- const char* pName,
- int* pValue)
-{
- // Only look for the class if locating the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getStaticIntField(%s)", pName);
-
- // Look up the field id.
- jfieldID fieldId = pEnv->GetStaticFieldID(clazz, pName, "I");
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the field could be located.
- if (NULL != fieldId)
- {
- // Retrieve the field value.
- (*pValue) = pEnv->GetStaticIntField(clazz, fieldId);
-
- // Log the value.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getStaticIntField, %s = %d", pName, (*pValue));
- }
- else
- {
- // Reset the result flag.
- (*pResult) = false;
-
- // Log the error.
- VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
- "videoEditJava_getStaticIntField, error: unable to locate field %s", pName);
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/NoSuchFieldException",
- "unable to locate static field");
- }
- }
-}
-
-void
-videoEditJava_initConstantClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_ConstantsClass* pClass)
-{
- bool gotten = true;
- jclass clazz = NULL;
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_initConstantClass(%s)", pClass->pName);
-
- // Only initialize the class once.
- if (!pClass->initialized)
- {
- // Look up the class.
- videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
- // Loop over the constants.
- for (index = 0; index < pClass->count; index++)
- {
- // Look up the constant.
- videoEditJava_getStaticIntField(pResult, pEnv, clazz,
- pClass->pConstants[index].pName,
- &pClass->pConstants[index].java);
- }
-
- // Check if all constants could be located.
- if (*pResult)
- {
- // Set the initialized flag.
- pClass->initialized = true;
- }
- }
- }
-}
-
-const char*
-videoEditJava_getConstantClassName(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- VideoEditJava_UnknownConstant unknown)
-{
- const char* pName = M4OSA_NULL;
- int index = 0;
-
- // Loop over the list with constants.
- for (index = 0;
- ((M4OSA_NULL == pName) && (index < pClass->count));
- index++)
- {
- // Check if the specified value matches the c value of the constant.
- if (value == pClass->pConstants[index].c)
- {
- // Set the name.
- pName = pClass->pConstants[index].pName;
- }
- }
-
- // Check if no constant was found.
- if (M4OSA_NULL == pName)
- {
- // Check if a function was specified to handle this case.
- if (M4OSA_NULL != unknown)
- {
- // Pass the constant to the specified unknown function.
- pName = unknown(value);
- }
- else
- {
- // Set the description to a default value.
- pName = "<unknown>";
- }
- }
-
- // Return the result.
- return(pName);
-}
-
-const char*
-videoEditJava_getConstantClassString(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- VideoEditJava_UnknownConstant unknown)
-{
- const char* pString = M4OSA_NULL;
- int index = 0;
-
- // Loop over the list with constants.
- for (index = 0;
- ((M4OSA_NULL == pString) && (index < pClass->count));
- index++)
- {
- // Check if the specified value matches the c value of the constant.
- if (value == pClass->pConstants[index].c)
- {
- // Set the description.
- pString = pClass->pConstants[index].pDescription;
- }
- }
-
- // Check if no constant was found.
- if (M4OSA_NULL == pString)
- {
- // Check if a function was specified to handle this case.
- if (M4OSA_NULL != unknown)
- {
- // Pass the constant to the specified unknown function.
- pString = unknown(value);
- }
- else
- {
- // Set the description to a default value.
- pString = "<unknown>";
- }
- }
-
- // Return the result.
- return(pString);
-}
-
-int
-videoEditJava_getConstantClassJavaToC(
- bool* pResult,
- const VideoEditJava_ConstantsClass* pClass,
- int value)
-{
- bool gotten = false;
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Loop over the list with constants.
- for (index = 0; ((!gotten) && (index < pClass->count)); index++)
- {
- // Check if the specified value matches the java value of the constant.
- if (value == pClass->pConstants[index].java)
- {
- // Set the value to the c value.
- value = pClass->pConstants[index].c;
-
- // Set the gotten flag.
- gotten = true;
- }
- }
-
- // Check if the value was not found.
- if (!gotten)
- {
- (*pResult) = false;
- }
- }
-
- // Return the translated value.
- return(value);
-}
-
-int
-videoEditJava_getConstantClassJavaToC(
- bool* pResult,
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- int unknown)
-{
- bool gotten = false;
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Loop over the list with constants.
- for (index = 0; ((!gotten) && (index < pClass->count)); index++)
- {
- // Check if the specified value matches the java value of the constant.
- if (value == pClass->pConstants[index].java)
- {
- // Set the value to the c value.
- value = pClass->pConstants[index].c;
-
- // Set the gotten flag.
- gotten = true;
- }
- }
-
- // If the constant was not found, look for the specified unknown.
- if (!gotten)
- {
- // Set the value to the c value.
- value = unknown;
- }
- }
-
- // Return the translated value.
- return(value);
-}
-
-int
-videoEditJava_getConstantClassCToJava(
- const VideoEditJava_ConstantsClass* pClass,
- int value)
-{
- bool gotten = false;
- int index = 0;
-
- // Loop over the list with constants.
- for (index = 0; ((!gotten) && (index < pClass->count)); index++)
- {
- // Check if the specified value matches the c value of the constant.
- if (value == pClass->pConstants[index].c)
- {
- // Set the value to the java value.
- value = pClass->pConstants[index].java;
-
- // Set the gotten flag.
- gotten = true;
- }
- }
-
- // Return the translated value.
- return(value);
-}
-
-int
-videoEditJava_getConstantClassCToJava(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- int unknown)
-{
- bool gotten = false;
- int index = 0;
-
- // Loop over the list with constants.
- for (index = 0; ((!gotten) && (index < pClass->count)); index++)
- {
- // Check if the specified value matches the c value of the constant.
- if (value == pClass->pConstants[index].c)
- {
- // Set the value to the java value.
- value = pClass->pConstants[index].java;
-
- // Set the gotten flag.
- gotten = true;
- }
- }
-
- // If the constant was not found, look for the specified unknown.
- if (!gotten)
- {
- // Loop over the list with constants.
- for (index = 0; ((!gotten) && (index < pClass->count)); index++)
- {
- // Check if the specified value matches the java value of the constant.
- if (unknown == pClass->pConstants[index].c)
- {
- // Set the value to the c value.
- value = pClass->pConstants[index].java;
-
- // Set the gotten flag.
- gotten = true;
- }
- }
- }
-
- // Return the translated value.
- return(value);
-}
-
-void
-videoEditJava_initFieldClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_FieldsClass* pClass)
-{
- bool gotten = true;
- jclass clazz = NULL;
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_initFieldClass(%s)", pClass->pName);
-
- // Only initialize the class once.
- if (!pClass->initialized)
- {
- // Look up the class.
- videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
- // Loop over the fields.
- for (index = 0; index < pClass->count; index++)
- {
- // Look up the field id.
- videoEditJava_getFieldId(
- pResult,
- pEnv,
- clazz,
- pClass->pFields[index].pName,
- pClass->pFields[index].pType,
- &pClass->pFields[index].fieldId);
- }
-
- // Check if all fields could be located.
- if (*pResult)
- {
- // Set the initialized flag.
- pClass->initialized = true;
- }
- }
- }
-}
-
-void
-videoEditJava_fieldClassClass(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_FieldsClass* pClass,
- jclass* pClazz)
-{
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the class is initialized.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
- "field class not initialized");
-
- // Get the class.
- videoEditJava_getClass(pResult, pEnv, pClass->pName, pClazz);
- }
-}
-
-void
-videoEditJava_fieldClassFieldIds(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_FieldsClass* pClass,
- int count,
- VideoEditJava_FieldIds* pIds)
-{
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the class is initialized.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
- "field class not initialized");
-
- // Check if the number of fields matches.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
- (pClass->count != count),
- "field class type mismatch");
-
- // Check if the class and object are valid.
- if (*pResult)
- {
- // Loop over the class fields.
- for (index = 0; index < count; index++)
- {
- // Copy the field ids.
- pIds->fieldIds[index] = pClass->pFields[index].fieldId;
- }
- }
- }
-}
-
-void
-videoEditJava_initMethodClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_MethodsClass* pClass)
-{
- bool gotten = true;
- jclass clazz = NULL;
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Log the function call.
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
- "videoEditJava_initMethodClass(%s)", pClass->pName);
-
- // Only initialize the class once.
- if (!pClass->initialized)
- {
- // Look up the class.
- videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
- // Loop over the methods.
- for (index = 0; index < pClass->count; index++)
- {
- // Look up the method id.
- videoEditJava_getMethodId(
- pResult,
- pEnv,
- clazz,
- pClass->pMethods[index].pName,
- pClass->pMethods[index].pType,
- &pClass->pMethods[index].methodId);
- }
-
- // Check if all methods could be located.
- if (*pResult)
- {
- // Set the initialized flag.
- pClass->initialized = true;
- }
- }
- }
-}
-
-void
-videoEditJava_methodClassMethodIds(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_MethodsClass* pClass,
- int count,
- VideoEditJava_MethodIds* pIds)
-{
- int index = 0;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Check if the class is initialized.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
- "method class not initialized");
-
- // Check if the number of methods matches.
- videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,\
- (pClass->count != count),
- "method class type mismatch");
-
- // Check if the class and object are valid.
- if (*pResult)
- {
- // Loop over the class methods.
- for (index = 0; index < count; index++)
- {
- // Copy the method ids.
- pIds->methodIds[index] = pClass->pMethods[index].methodId;
- }
- }
- }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorJava.h b/media/jni/mediaeditor/VideoEditorJava.h
deleted file mode 100644
index 0a2db08..0000000
--- a/media/jni/mediaeditor/VideoEditorJava.h
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDiTOR_JAVA_H
-#define VIDEO_EDiTOR_JAVA_H
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-/**
- ************************************************************************
- * @file VideoEditorJava.h
- * @brief Interface for JNI methods that have specific access to
- * class, objects and method Ids defined in Java layer
- ************************************************************************
-*/
-
-extern "C" {
-#include <M4OSA_Types.h>
-#include <M4OSA_Error.h>
-}
-
-#define VIDEOEDIT_JAVA_CONSTANT_INIT(m_name, m_c) \
- { m_name, \
- 0, \
- m_c, \
- #m_c }
-
-#define VIDEOEDIT_JAVA_DEFINE_CONSTANTS(m_class) \
-static \
-VideoEditJava_Constant g##m_class##Constants [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS( \
- m_class, \
- m_name, \
- m_unknownName, \
- m_unknownString) \
- \
-static VideoEditJava_ConstantsClass g##m_class##ConstantsClass = \
-{ m_name, \
- &g##m_class##Constants[0], \
- (sizeof(g##m_class##Constants) / sizeof(VideoEditJava_Constant)), \
- false \
-}; \
- \
- \
-void videoEditJava_init##m_class##Constants( \
- bool* pResult, \
- JNIEnv* pEnv) \
-{ \
- videoEditJava_initConstantClass( \
- pResult, \
- pEnv, \
- &g##m_class##ConstantsClass); \
-} \
- \
-const char* videoEditJava_get##m_class##Name( \
- int value) \
-{ \
- return(videoEditJava_getConstantClassName( \
- &g##m_class##ConstantsClass, \
- value, \
- m_unknownName)); \
-} \
- \
-const char* videoEditJava_get##m_class##String( \
- int value) \
-{ \
- return(videoEditJava_getConstantClassString( \
- &g##m_class##ConstantsClass, \
- value, \
- m_unknownString)); \
-} \
- \
-int \
-videoEditJava_get##m_class##JavaToC( \
- bool* pResult, \
- int value) \
-{ \
- return(videoEditJava_getConstantClassJavaToC( \
- pResult, \
- &g##m_class##ConstantsClass, \
- value)); \
-} \
- \
-int \
-videoEditJava_get##m_class##JavaToC( \
- bool* pResult, \
- int value, \
- int unknown) \
-{ \
- return(videoEditJava_getConstantClassJavaToC( \
- pResult, \
- &g##m_class##ConstantsClass, \
- value, \
- unknown)); \
-} \
- \
-int \
-videoEditJava_get##m_class##CToJava( \
- int value) \
-{ \
- return(videoEditJava_getConstantClassCToJava( \
- &g##m_class##ConstantsClass, \
- value)); \
-} \
- \
-int \
-videoEditJava_get##m_class##CToJava( \
- int value, \
- int unknown) \
-{ \
- return(videoEditJava_getConstantClassCToJava( \
- &g##m_class##ConstantsClass, \
- value, \
- unknown)); \
-}
-
-
-#define VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(m_class) \
-void \
-videoEditJava_init##m_class##Constants( \
- bool* pResult, \
- JNIEnv* pEnv); \
- \
-const char* \
-videoEditJava_get##m_class##Name( \
- int value); \
- \
-const char* \
-videoEditJava_get##m_class##String( \
- int value); \
- \
-int \
-videoEditJava_get##m_class##JavaToC( \
- bool* pResult, \
- int value, \
- int unknown); \
- \
-int \
-videoEditJava_get##m_class##JavaToC( \
- bool* pResult, \
- int value); \
- \
-int \
-videoEditJava_get##m_class##CToJava( \
- int value); \
- \
-int \
-videoEditJava_get##m_class##CToJava( \
- int value, \
- int unknown);
-
-#define VIDEOEDIT_JAVA_FIELD_INIT(m_name, m_type) \
- { m_name, \
- m_type, \
- NULL }
-
-#define VIDEOEDIT_JAVA_DEFINE_FIELDS(m_class) \
-static \
-VideoEditJava_Field g##m_class##Fields [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(m_class, m_name) \
-static VideoEditJava_FieldsClass g##m_class##FieldsClass = \
- { m_name, \
- &g##m_class##Fields[0], \
- (sizeof(g##m_class##Fields) / sizeof(VideoEditJava_Field)), \
- false }; \
- \
-void \
-videoEditJava_init##m_class##Fields( \
- bool* pResult, \
- JNIEnv* pEnv) \
-{ \
- videoEditJava_initFieldClass( \
- pResult, \
- pEnv, \
- &g##m_class##FieldsClass); \
-} \
- \
-void \
-videoEditJava_get##m_class##Class( \
- bool* pResult, \
- JNIEnv* pEnv, \
- jclass* pClazz) \
-{ \
- videoEditJava_fieldClassClass( \
- pResult, \
- pEnv, \
- &g##m_class##FieldsClass, \
- pClazz); \
-} \
- \
-void \
-videoEditJava_get##m_class##FieldIds( \
- bool* pResult, \
- JNIEnv* pEnv, \
- VideoEditJava_##m_class##FieldIds* pIds) \
-{ \
- videoEditJava_fieldClassFieldIds( \
- pResult, \
- pEnv, \
- &g##m_class##FieldsClass, \
- (sizeof(VideoEditJava_##m_class##FieldIds) / \
- sizeof(jfieldID)), \
- (VideoEditJava_FieldIds*)pIds); \
-}
-
-#define VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(m_class) \
-void \
-videoEditJava_init##m_class##Fields( \
- bool* pResult, \
- JNIEnv* pEnv); \
- \
-void \
-videoEditJava_get##m_class##Class( \
- bool* pResult, \
- JNIEnv* pEnv, \
- jclass* pClazz); \
- \
-void \
-videoEditJava_get##m_class##FieldIds( \
- bool* pResult, \
- JNIEnv* pEnv, \
- VideoEditJava_##m_class##FieldIds* pIds);
-
-
-#define VIDEOEDIT_JAVA_METHOD_INIT(m_name, m_type) \
- { m_name, \
- m_type, \
- NULL }
-
-#define VIDEOEDIT_JAVA_DEFINE_METHODS(m_class) \
-static \
-VideoEditJava_Method g##m_class##Methods [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_METHOD_CLASS(m_class, m_name) \
-static VideoEditJava_MethodsClass g##m_class##MethodsClass = \
- { m_name, \
- &g##m_class##Methods[0], \
- (sizeof(g##m_class##Methods) / sizeof(VideoEditJava_Method)), \
- false }; \
- \
-void \
-videoEditJava_init##m_class##Methods( \
- bool* pResult, \
- JNIEnv* pEnv) \
-{ \
- videoEditJava_initMethodClass( \
- pResult, \
- pEnv, \
- &g##m_class##MethodsClass); \
-} \
- \
-void \
-videoEditJava_get##m_class##MethodIds( \
- bool* pResult, \
- JNIEnv* pEnv, \
- VideoEditJava_##m_class##MethodIds* pIds) \
-{ \
- videoEditJava_methodClassMethodIds( \
- pResult, \
- pEnv, \
- &g##m_class##MethodsClass, \
- (sizeof(VideoEditJava_##m_class##MethodIds) / \
- sizeof(jmethodID)), \
- (VideoEditJava_MethodIds*)pIds); \
-}
-
-#define VIDEOEDIT_JAVA_DECLARE_METHOD_CLASS(m_class) \
-void \
-videoEditJava_init##m_class##Methods( \
- bool* pResult, \
- JNIEnv* pEnv); \
- \
-void \
-videoEditJava_get##m_class##MethodIds( \
- bool* pResult, \
- JNIEnv* pEnv, \
- VideoEditJava_##m_class##MethodIds* pIds);
-
-
-typedef struct
-{
- const char* pName;
- int java;
- int c;
- const char* pDescription;
-} VideoEditJava_Constant;
-
-typedef struct
-{
- const char* pName;
- VideoEditJava_Constant* pConstants;
- int count;
- bool initialized;
-} VideoEditJava_ConstantsClass;
-
-typedef const char* (*VideoEditJava_UnknownConstant)(int constant);
-
-typedef struct
-{
- const char* pName;
- const char* pType;
- jfieldID fieldId;
-} VideoEditJava_Field;
-
-typedef struct
-{
- const char* pName;
- VideoEditJava_Field* pFields;
- int count;
- bool initialized;
-} VideoEditJava_FieldsClass;
-
-typedef struct
-{
- jfieldID fieldIds[];
-} VideoEditJava_FieldIds;
-
-typedef struct
-{
- const char* pName;
- const char* pType;
- jmethodID methodId;
-} VideoEditJava_Method;
-
-typedef struct
-{
- const char* pName;
- VideoEditJava_Method* pMethods;
- int count;
- bool initialized;
-} VideoEditJava_MethodsClass;
-
-typedef struct
-{
- jmethodID methodIds[];
-} VideoEditJava_MethodIds;
-
-#define videoEditJava_checkAndThrowIllegalArgumentException(\
- a, b, c, d) videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(\
- a, b, c, d, __FILE__, __LINE__)
-
-#define videoEditJava_checkAndThrowRuntimeException(\
- a, b, c, d) videoEditJava_checkAndThrowRuntimeExceptionFunc(\
- a, b, c, d, __FILE__, __LINE__)
-
-#define videoEditJava_checkAndThrowIllegalStateException(\
- a, b, c, d) videoEditJava_checkAndThrowIllegalStateExceptionFunc(\
- a, b, c, d, __FILE__, __LINE__)
-
-void
-videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- const char* pMessage,
- const char* pFile,
- int lineNo
- );
-
-void
-videoEditJava_checkAndThrowRuntimeExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- M4OSA_ERR result,
- const char* pFile,
- int lineNo
- );
-
-void
-videoEditJava_checkAndThrowIllegalStateExceptionFunc(
- bool* pResult,
- JNIEnv* pEnv,
- bool condition,
- const char* pMessage,
- const char* pFile,
- int lineNo
- );
-
-void
-videoEditJava_getClass(
- bool* pResult,
- JNIEnv* pEnv,
- const char* pName,
- jclass* pClazz);
-
-void
-videoEditJava_getMethodId(
- bool* pResult,
- JNIEnv* pEnv,
- jclass clazz,
- const char* pName,
- const char* pType,
- jmethodID* pMethodId);
-
-void videoEditJava_getFieldId(
- bool* pResult,
- JNIEnv* pEnv,
- jclass clazz,
- const char* pName,
- const char* pType,
- jfieldID* pFieldId);
-
-void videoEditJava_getObject(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID objectFieldId,
- jobject* pObject);
-
-void videoEditJava_getArray(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID arrayFieldId,
- jobjectArray* pArray,
- jsize* pArraySize);
-
-void* videoEditJava_getString(
- bool* pResult,
- JNIEnv* pEnv,
- jobject object,
- jfieldID stringFieldId,
- M4OSA_UInt32* pLength);
-
-void videoEditJava_getStaticIntField(
- bool* pResult,
- JNIEnv* env,
- jclass clazz,
- const char* pName,
- int* pValue);
-
-void
-videoEditJava_initConstantClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_ConstantsClass* pClass);
-
-const char*
-videoEditJava_getConstantClassName(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- VideoEditJava_UnknownConstant unknown);
-
-const char*
-videoEditJava_getConstantClassString(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- VideoEditJava_UnknownConstant unknown);
-
-int
-videoEditJava_getConstantClassJavaToC(
- bool* pResult,
- const VideoEditJava_ConstantsClass* pClass,
- int value);
-
-int
-videoEditJava_getConstantClassJavaToC(
- bool* pResult,
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- int unknown);
-
-int
-videoEditJava_getConstantClassCToJava(
- const VideoEditJava_ConstantsClass* pClass,
- int value);
-
-int
-videoEditJava_getConstantClassCToJava(
- const VideoEditJava_ConstantsClass* pClass,
- int value,
- int unknown);
-
-void
-videoEditJava_initFieldClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_FieldsClass* pClass);
-
-void
-videoEditJava_fieldClassClass(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_FieldsClass* pClass,
- jclass* pClazz);
-
-void
-videoEditJava_fieldClassFieldIds(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_FieldsClass* pClass,
- int count,
- VideoEditJava_FieldIds* pIds);
-
-void
-videoEditJava_initMethodClass(
- bool* pResult,
- JNIEnv* pEnv,
- VideoEditJava_MethodsClass* pClass);
-
-void
-videoEditJava_methodClassMethodIds(
- bool* pResult,
- JNIEnv* pEnv,
- const VideoEditJava_MethodsClass* pClass,
- int count,
- VideoEditJava_MethodIds* pIds);
-
-#endif // VIDEO_EDiTOR_JAVA_H
-
diff --git a/media/jni/mediaeditor/VideoEditorLogging.h b/media/jni/mediaeditor/VideoEditorLogging.h
deleted file mode 100644
index 1f1228a..0000000
--- a/media/jni/mediaeditor/VideoEditorLogging.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_LOGGING_H
-#define VIDEO_EDITOR_LOGGING_H
-
-#ifndef LOG_TAG
-#error "No LOG_TAG defined!"
-#endif
-
-/*
- * This file is used as a proxy for cutils/log.h. Include cutils/log.h here to
- * avoid relying on import ordering.
- */
-#include <cutils/log.h>
-
-//#define VIDEOEDIT_LOGGING_ENABLED
-
-#define VIDEOEDIT_LOG_INDENTATION (3)
-
-#define VIDEOEDIT_LOG_ERROR __android_log_print
-#define VIDEOEDIT_LOG_EXCEPTION __android_log_print
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-
-#define VIDEOEDIT_LOG_ALLOCATION __android_log_print
-#define VIDEOEDIT_LOG_API __android_log_print
-#define VIDEOEDIT_LOG_FUNCTION __android_log_print
-#define VIDEOEDIT_LOG_RESULT(x,y, ...) ALOGI(y, __VA_ARGS__ )
-#define VIDEOEDIT_LOG_SETTING __android_log_print
-#define VIDEOEDIT_LOG_EDIT_SETTINGS(m_settings) videoEditClasses_logEditSettings\
- (m_settings, VIDEOEDIT_LOG_INDENTATION)
-#define VIDEOEDIT_PROP_LOG_PROPERTIES(m_properties) videoEditPropClass_logProperties\
- (m_properties, VIDEOEDIT_LOG_INDENTATION)
-#define VIDEOEDIT_PROP_LOG_RESULT __android_log_print
-
-#else
-
-#define VIDEOEDIT_LOG_ALLOCATION (void)
-#define VIDEOEDIT_LOG_API (void)
-#define VIDEOEDIT_LOG_FUNCTION (void)
-#define VIDEOEDIT_LOG_RESULT (void)
-#define VIDEOEDIT_LOG_SETTING (void)
-#define VIDEOEDIT_LOG_EDIT_SETTINGS(m_settings) (void)m_settings
-#define VIDEOEDIT_PROP_LOG_PROPERTIES(m_properties) (void)m_properties
-#define VIDEOEDIT_PROP_LOG_RESULT (void)
-
-#endif
-
-#endif // VIDEO_EDITOR_LOGGING_H
-
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
deleted file mode 100644
index 0894d74..0000000
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ /dev/null
@@ -1,3639 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-#define LOG_NDEBUG 1
-#define LOG_TAG "VideoEditorMain"
-#include <dlfcn.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorOsal.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorThumbnailMain.h>
-#include <M4OSA_Debug.h>
-#include <M4xVSS_Internal.h>
-#include <gui/Surface.h>
-#include "VideoEditorPreviewController.h"
-
-#include "VideoEditorMain.h"
-
-#include <android_runtime/android_view_Surface.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_Error.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_API.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-};
-
-
-using namespace android;
-
-#define THREAD_STACK_SIZE (65536)
-
-#define VIDEOEDITOR_VERSION_MAJOR 0
-#define VIDEOEDITOR_VERSION_MINOR 0
-#define VIDEOEDITOR_VERSION_REVISION 1
-
-
-typedef enum
-{
- ManualEditState_NOT_INITIALIZED,
- ManualEditState_INITIALIZED,
- ManualEditState_ANALYZING,
- ManualEditState_ANALYZING_ERROR,
- ManualEditState_OPENED,
- ManualEditState_SAVING,
- ManualEditState_SAVING_ERROR,
- ManualEditState_SAVED,
- ManualEditState_STOPPING
-} ManualEditState;
-
-typedef struct
-{
- JavaVM* pVM;
- jobject engine;
- jmethodID onCompletionMethodId;
- jmethodID onErrorMethodId;
- jmethodID onWarningMethodId;
- jmethodID onProgressUpdateMethodId;
- jmethodID onPreviewProgressUpdateMethodId;
- jmethodID previewFrameEditInfoId;
- M4xVSS_InitParams initParams;
- void* pTextRendererHandle;
- M4xVSS_getTextRgbBufferFct pTextRendererFunction;
- M4OSA_Context engineContext;
- ManualEditState state;
- M4VSS3GPP_EditSettings* pEditSettings;
- M4OSA_Context threadContext;
- M4OSA_ERR threadResult;
- M4OSA_UInt8 threadProgress;
- VideoEditorPreviewController *mPreviewController;
- M4xVSS_AudioMixingSettings *mAudioSettings;
- /* Audio Graph changes */
- M4OSA_Context pAudioGraphMCSCtx;
- M4OSA_Bool bSkipState;
- jmethodID onAudioGraphProgressUpdateMethodId;
- Mutex mLock;
- bool mIsUpdateOverlay;
- char *mOverlayFileName;
- int mOverlayRenderingMode;
- M4DECODER_VideoDecoders* decoders;
-} ManualEditContext;
-
-extern "C" M4OSA_ERR M4MCS_open_normalMode(
- M4MCS_Context pContext,
- M4OSA_Void* pFileIn,
- M4VIDEOEDITING_FileType InputFileType,
- M4OSA_Void* pFileOut,
- M4OSA_Void* pTempFile);
-
-static M4OSA_ERR videoEditor_toUTF8Fct(
- M4OSA_Void* pBufferIn,
- M4OSA_UInt8* pBufferOut,
- M4OSA_UInt32* bufferOutSize);
-
-static M4OSA_ERR videoEditor_fromUTF8Fct(
- M4OSA_UInt8* pBufferIn,
- M4OSA_Void* pBufferOut,
- M4OSA_UInt32* bufferOutSize);
-
-static M4OSA_ERR videoEditor_getTextRgbBufferFct(
- M4OSA_Void* pRenderingData,
- M4OSA_Void* pTextBuffer,
- M4OSA_UInt32 textBufferSize,
- M4VIFI_ImagePlane** pOutputPlane);
-
-static void videoEditor_callOnProgressUpdate(
- ManualEditContext* pContext,
- int task,
- int progress);
-
-static void videoEditor_freeContext(
- JNIEnv* pEnv,
- ManualEditContext** ppContext);
-
-static M4OSA_ERR videoEditor_threadProc(
- M4OSA_Void* param);
-
-static jobject videoEditor_getVersion(
- JNIEnv* pEnv,
- jobject thiz);
-
-static void videoEditor_init(
- JNIEnv* pEnv,
- jobject thiz,
- jstring tempPath,
- jstring textRendererPath);
-
-static void videoEditor_loadSettings(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings);
-
-static void videoEditor_unloadSettings(
- JNIEnv* pEnv,
- jobject thiz);
-
-
-static void videoEditor_stopEncoding(
- JNIEnv* pEnv,
- jobject thiz);
-
-static void videoEditor_release(
- JNIEnv* pEnv,
- jobject thiz);
-static jint videoEditor_getPixels(
- JNIEnv* env,
- jobject thiz,
- jstring path,
- jintArray pixelArray,
- M4OSA_UInt32 width,
- M4OSA_UInt32 height,
- M4OSA_UInt32 timeMS);
-static jint videoEditor_getPixelsList(
- JNIEnv* env,
- jobject thiz,
- jstring path,
- jintArray pixelArray,
- M4OSA_UInt32 width,
- M4OSA_UInt32 height,
- M4OSA_UInt32 noOfThumbnails,
- jlong startTime,
- jlong endTime,
- jintArray indexArray,
- jobject callback);
-
-static void
-videoEditor_startPreview(
- JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jlong fromMs,
- jlong toMs,
- jint callbackInterval,
- jboolean loop);
-
-static void
-videoEditor_populateSettings(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings,
- jobject object,
- jobject audioSettingObject);
-
-static jint videoEditor_stopPreview(JNIEnv* pEnv,
- jobject thiz);
-
-static jobject
-videoEditor_getProperties(
- JNIEnv* pEnv,
- jobject thiz,
- jstring file);
-
-static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jlong fromMs,
- jint surfaceWidth,
- jint surfaceHeight);
-
-static int videoEditor_registerManualEditMethods(
- JNIEnv* pEnv);
-
-static void jniPreviewProgressCallback(void* cookie, M4OSA_UInt32 msgType,
- void *argc);
-
-static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jstring filePath,
- jint frameWidth,
- jint frameHeight,
- jint surfaceWidth,
- jint surfaceHeight,
- jlong fromMs);
-
-static jint videoEditor_generateAudioWaveFormSync ( JNIEnv* pEnv,
- jobject thiz,
- jstring pcmfilePath,
- jstring outGraphfilePath,
- jint frameDuration,
- jint channels,
- jint samplesCount);
-
-static int videoEditor_generateAudioRawFile(JNIEnv* pEnv,
- jobject thiz,
- jstring infilePath,
- jstring pcmfilePath );
-
-M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext,
- M4OSA_Char* infilePath,
- M4OSA_Char* pcmfilePath );
-
-static jint
-videoEditor_generateClip(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings);
-
-static void videoEditor_clearSurface(JNIEnv* pEnv,
- jobject thiz,
- jobject surface);
-
-static JNINativeMethod gManualEditMethods[] = {
- {"getVersion", "()L"VERSION_CLASS_NAME";",
- (void *)videoEditor_getVersion },
- {"_init", "(Ljava/lang/String;Ljava/lang/String;)V",
- (void *)videoEditor_init },
- {"nativeStartPreview", "(Landroid/view/Surface;JJIZ)V",
- (void *)videoEditor_startPreview },
- {"nativePopulateSettings",
- "(L"EDIT_SETTINGS_CLASS_NAME";L"PREVIEW_PROPERTIES_CLASS_NAME";L"
- AUDIO_SETTINGS_CLASS_NAME";)V",
- (void *)videoEditor_populateSettings },
- {"nativeRenderPreviewFrame", "(Landroid/view/Surface;JII)I",
- (int *)videoEditor_renderPreviewFrame },
- {"nativeRenderMediaItemPreviewFrame",
- "(Landroid/view/Surface;Ljava/lang/String;IIIIJ)I",
- (int *)videoEditor_renderMediaItemPreviewFrame },
- {"nativeStopPreview", "()I",
- (int *)videoEditor_stopPreview },
- {"stopEncoding", "()V",
- (void *)videoEditor_stopEncoding },
- {"release", "()V",
- (void *)videoEditor_release },
- {"nativeGetPixels", "(Ljava/lang/String;[IIIJ)I",
- (void*)videoEditor_getPixels },
- {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
- (void*)videoEditor_getPixelsList },
- {"getMediaProperties",
- "(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;",
- (void *)videoEditor_getProperties },
- {"nativeGenerateAudioGraph","(Ljava/lang/String;Ljava/lang/String;III)I",
- (int *)videoEditor_generateAudioWaveFormSync },
- {"nativeGenerateRawAudio", "(Ljava/lang/String;Ljava/lang/String;)I",
- (int *)videoEditor_generateAudioRawFile },
- {"nativeGenerateClip", "(L"EDIT_SETTINGS_CLASS_NAME";)I",
- (void *)videoEditor_generateClip },
- {"nativeClearSurface", "(Landroid/view/Surface;)V",
- (void *)videoEditor_clearSurface },
-};
-
-// temp file name of VSS out file
-#define TEMP_MCS_OUT_FILE_PATH "tmpOut.3gp"
-
-void
-getClipSetting(
- JNIEnv* pEnv,
- jobject object,
- M4VSS3GPP_ClipSettings* pSettings)
-{
-
- jfieldID fid;
- int field = 0;
- bool needToBeLoaded = true;
- jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME);
-
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == clazz),
- "not initialized");
-
- fid = pEnv->GetFieldID(clazz,"duration","I");
- pSettings->ClipProperties.uiClipDuration = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("duration = %d",pSettings->ClipProperties.uiClipDuration);
-
- fid = pEnv->GetFieldID(clazz,"videoFormat","I");
- pSettings->ClipProperties.VideoStreamType =
- (M4VIDEOEDITING_VideoFormat)pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("videoFormat = %d",pSettings->ClipProperties.VideoStreamType);
-
- fid = pEnv->GetFieldID(clazz,"videoDuration","I");
- pSettings->ClipProperties.uiClipVideoDuration = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("videoDuration = %d",
- pSettings->ClipProperties.uiClipVideoDuration);
-
- fid = pEnv->GetFieldID(clazz,"width","I");
- pSettings->ClipProperties.uiVideoWidth = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("width = %d",pSettings->ClipProperties.uiVideoWidth);
-
- fid = pEnv->GetFieldID(clazz,"height","I");
- pSettings->ClipProperties.uiVideoHeight = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("height = %d",pSettings->ClipProperties.uiVideoHeight);
-
- fid = pEnv->GetFieldID(clazz,"audioFormat","I");
- pSettings->ClipProperties.AudioStreamType =
- (M4VIDEOEDITING_AudioFormat)pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioFormat = %d",pSettings->ClipProperties.AudioStreamType);
-
- fid = pEnv->GetFieldID(clazz,"audioDuration","I");
- pSettings->ClipProperties.uiClipAudioDuration = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioDuration = %d",
- pSettings->ClipProperties.uiClipAudioDuration);
-
- fid = pEnv->GetFieldID(clazz,"audioBitrate","I");
- pSettings->ClipProperties.uiAudioBitrate = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioBitrate = %d",pSettings->ClipProperties.uiAudioBitrate);
-
- fid = pEnv->GetFieldID(clazz,"audioChannels","I");
- pSettings->ClipProperties.uiNbChannels = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioChannels = %d",pSettings->ClipProperties.uiNbChannels);
-
- fid = pEnv->GetFieldID(clazz,"audioSamplingFrequency","I");
- pSettings->ClipProperties.uiSamplingFrequency = pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioSamplingFrequency = %d",
- pSettings->ClipProperties.uiSamplingFrequency);
-
- fid = pEnv->GetFieldID(clazz,"audioVolumeValue","I");
- pSettings->ClipProperties.uiClipAudioVolumePercentage =
- pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("audioVolumeValue = %d",
- pSettings->ClipProperties.uiClipAudioVolumePercentage);
-
- fid = pEnv->GetFieldID(clazz,"videoRotation","I");
- pSettings->ClipProperties.videoRotationDegrees =
- pEnv->GetIntField(object,fid);
- M4OSA_TRACE1_1("videoRotation = %d",
- pSettings->ClipProperties.videoRotationDegrees);
-
- // Free the local references to avoid memory leaks
- pEnv->DeleteLocalRef(clazz);
-}
-
-static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType,
- void *argc)
-{
- ManualEditContext *pContext = (ManualEditContext *)cookie;
- JNIEnv* pEnv = NULL;
- bool isFinished = false;
- int currentMs = 0;
- int error = M4NO_ERROR;
- bool isUpdateOverlay = false;
- int overlayEffectIndex;
- char *extPos;
- bool isSendProgress = true;
- jstring tmpFileName;
- VideoEditorCurretEditInfo *pCurrEditInfo;
-
- // Attach the current thread.
- pContext->pVM->AttachCurrentThread(&pEnv, NULL);
- switch(msgType)
- {
- case MSG_TYPE_PROGRESS_INDICATION:
- currentMs = *(int*)argc;
- break;
- case MSG_TYPE_PLAYER_ERROR:
- currentMs = -1;
- error = *(int*)argc;
- break;
- case MSG_TYPE_PREVIEW_END:
- isFinished = true;
- break;
- case MSG_TYPE_OVERLAY_UPDATE:
- {
- int overlayFileNameLen = 0;
- isSendProgress = false;
- pContext->mIsUpdateOverlay = true;
- pCurrEditInfo = (VideoEditorCurretEditInfo*)argc;
- overlayEffectIndex = pCurrEditInfo->overlaySettingsIndex;
- ALOGV("MSG_TYPE_OVERLAY_UPDATE");
-
- if (pContext->mOverlayFileName != NULL) {
- free(pContext->mOverlayFileName);
- pContext->mOverlayFileName = NULL;
- }
-
- overlayFileNameLen =
- strlen((const char*)pContext->pEditSettings->Effects[overlayEffectIndex].xVSS.pFramingFilePath);
-
- pContext->mOverlayFileName =
- (char*)M4OSA_32bitAlignedMalloc(overlayFileNameLen+1,
- M4VS, (M4OSA_Char*)"videoEdito JNI overlayFile");
- if (pContext->mOverlayFileName != NULL) {
- strncpy (pContext->mOverlayFileName,
- (const char*)pContext->pEditSettings->
- Effects[overlayEffectIndex].xVSS.pFramingFilePath, overlayFileNameLen);
- //Change the name to png file
- extPos = strstr(pContext->mOverlayFileName, ".rgb");
- if (extPos != NULL) {
- *extPos = '\0';
- } else {
- ALOGE("ERROR the overlay file is incorrect");
- }
-
- strcat(pContext->mOverlayFileName, ".png");
- ALOGV("Conv string is %s", pContext->mOverlayFileName);
- ALOGV("Current Clip index = %d", pCurrEditInfo->clipIndex);
-
- pContext->mOverlayRenderingMode = pContext->pEditSettings->\
- pClipList[pCurrEditInfo->clipIndex]->xVSS.MediaRendering;
- ALOGV("rendering mode %d ", pContext->mOverlayRenderingMode);
-
- }
-
- break;
- }
-
- case MSG_TYPE_OVERLAY_CLEAR:
- isSendProgress = false;
- if (pContext->mOverlayFileName != NULL) {
- free(pContext->mOverlayFileName);
- pContext->mOverlayFileName = NULL;
- }
-
- ALOGV("MSG_TYPE_OVERLAY_CLEAR");
- //argc is not used
- pContext->mIsUpdateOverlay = true;
- break;
- default:
- break;
- }
-
- if (isSendProgress) {
- tmpFileName = pEnv->NewStringUTF(pContext->mOverlayFileName);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onPreviewProgressUpdateMethodId,
- currentMs,isFinished, pContext->mIsUpdateOverlay,
- tmpFileName, pContext->mOverlayRenderingMode, error);
-
- if (pContext->mIsUpdateOverlay) {
- pContext->mIsUpdateOverlay = false;
- }
-
- if (tmpFileName) {
- pEnv->DeleteLocalRef(tmpFileName);
- }
- }
-
- // Detach the current thread.
- pContext->pVM->DetachCurrentThread();
-
-}
-static M4OSA_ERR checkClipVideoProfileAndLevel(M4DECODER_VideoDecoders *pDecoders,
- M4OSA_Int32 format, M4OSA_UInt32 profile, M4OSA_UInt32 level){
-
- M4OSA_Int32 codec = 0;
- M4OSA_Bool foundCodec = M4OSA_FALSE;
- M4OSA_ERR result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE;
- M4OSA_Bool foundProfile = M4OSA_FALSE;
- ALOGV("checkClipVideoProfileAndLevel format %d profile;%d level:0x%x",
- format, profile, level);
-
- switch (format) {
- case M4VIDEOEDITING_kH263:
- codec = M4DA_StreamTypeVideoH263;
- break;
- case M4VIDEOEDITING_kH264:
- codec = M4DA_StreamTypeVideoMpeg4Avc;
- break;
- case M4VIDEOEDITING_kMPEG4:
- codec = M4DA_StreamTypeVideoMpeg4;
- break;
- case M4VIDEOEDITING_kNoneVideo:
- case M4VIDEOEDITING_kNullVideo:
- case M4VIDEOEDITING_kUnsupportedVideo:
- // For these case we do not check the profile and level
- return M4NO_ERROR;
- default :
- ALOGE("checkClipVideoProfileAndLevel unsupport Video format %ld", format);
- break;
- }
-
- if (pDecoders != M4OSA_NULL && pDecoders->decoderNumber > 0) {
- VideoDecoder *pVideoDecoder = pDecoders->decoder;
- for(size_t k =0; k < pDecoders->decoderNumber; k++) {
- if (pVideoDecoder != M4OSA_NULL) {
- if (pVideoDecoder->codec == codec) {
- foundCodec = M4OSA_TRUE;
- break;
- }
- }
- pVideoDecoder++;
- }
-
- if (foundCodec) {
- VideoComponentCapabilities* pComponent = pVideoDecoder->component;
- for (size_t i = 0; i < pVideoDecoder->componentNumber; i++) {
- if (pComponent != M4OSA_NULL) {
- VideoProfileLevel *pProfileLevel = pComponent->profileLevel;
- for (size_t j =0; j < pComponent->profileNumber; j++) {
- // Check the profile and level
- if (pProfileLevel != M4OSA_NULL) {
- if (profile == pProfileLevel->mProfile) {
- foundProfile = M4OSA_TRUE;
-
- if (level <= pProfileLevel->mLevel) {
- return M4NO_ERROR;
- }
- } else {
- foundProfile = M4OSA_FALSE;
- }
- }
- pProfileLevel++;
- }
- }
- pComponent++;
- }
- }
- }
-
- if (foundProfile) {
- result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL;
- } else {
- result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE;
- }
-
- return result;
-}
-static jint videoEditor_stopPreview(JNIEnv* pEnv,
- jobject thiz)
-{
- ManualEditContext* pContext = M4OSA_NULL;
- bool needToBeLoaded = true;
- M4OSA_UInt32 lastProgressTimeMs = 0;
-
- // Get the context.
- pContext =
- (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
- lastProgressTimeMs = pContext->mPreviewController->stopPreview();
-
- if (pContext->mOverlayFileName != NULL) {
- free(pContext->mOverlayFileName);
- pContext->mOverlayFileName = NULL;
- }
-
- return (jint)lastProgressTimeMs;
-}
-
-static void videoEditor_clearSurface(JNIEnv* pEnv,
- jobject thiz,
- jobject surface)
-{
- bool needToBeLoaded = true;
- M4OSA_ERR result = M4NO_ERROR;
- VideoEditor_renderPreviewFrameStr frameStr;
- const char* pMessage = NULL;
- // Let the size be QVGA
- int width = 320;
- int height = 240;
- ManualEditContext* pContext = M4OSA_NULL;
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR","pContext = 0x%x",pContext);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
-
- // Validate the surface parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == surface),
- "surface is null");
-
- sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, surface);
-
- // Validate the mSurface's mNativeSurface field
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (NULL == previewSurface.get()),
- "mNativeSurface is null");
-
- frameStr.pBuffer = M4OSA_NULL;
- frameStr.timeMs = 0;
- frameStr.uiSurfaceWidth = width;
- frameStr.uiSurfaceHeight = height;
- frameStr.uiFrameWidth = width;
- frameStr.uiFrameHeight = height;
- frameStr.bApplyEffect = M4OSA_FALSE;
- frameStr.clipBeginCutTime = 0;
- frameStr.clipEndCutTime = 0;
-
- result = pContext->mPreviewController->clearSurface(previewSurface,
- &frameStr);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
-
- }
-
-static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jlong fromMs,
- jint surfaceWidth,
- jint surfaceHeight )
-{
- bool needToBeLoaded = true;
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs;
- M4OSA_UInt32 i=0,tnTimeMs = 0, framesizeYuv =0;
- M4VIFI_UInt8 *pixelArray = M4OSA_NULL;
- M4OSA_UInt32 iCurrentClipIndex = 0, uiNumberOfClipsInStoryBoard =0,
- uiClipDuration = 0, uiTotalClipDuration = 0,
- iIncrementedDuration = 0;
- VideoEditor_renderPreviewFrameStr frameStr;
- M4OSA_Context tnContext = M4OSA_NULL;
- const char* pMessage = NULL;
- M4VIFI_ImagePlane *yuvPlane = NULL;
- VideoEditorCurretEditInfo currEditInfo;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR", "surfaceWidth = %d",surfaceWidth);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR", "surfaceHeight = %d",surfaceHeight);
- ManualEditContext* pContext = M4OSA_NULL;
- // Get the context.
- pContext =
- (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR","pContext = 0x%x",pContext);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
-
- // Validate the mSurface parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == mSurface),
- "mSurface is null");
-
- sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
- // Validate the mSurface's mNativeSurface field
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (NULL == previewSurface.get()),
- "mNativeSurface is null");
-
- /* Determine the total number of clips, total duration*/
- uiNumberOfClipsInStoryBoard = pContext->pEditSettings->uiClipNumber;
-
- for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) {
- uiClipDuration = pContext->pEditSettings->pClipList[i]->uiEndCutTime -
- pContext->pEditSettings->pClipList[i]->uiBeginCutTime;
- uiTotalClipDuration += uiClipDuration;
- }
-
- /* determine the clip whose thumbnail needs to be rendered*/
- if (timeMs == 0) {
- iCurrentClipIndex = 0;
- i=0;
- } else {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() timeMs=%d", timeMs);
-
- if (timeMs > uiTotalClipDuration) {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() timeMs > uiTotalClipDuration");
- pMessage = videoEditJava_getErrorName(M4ERR_PARAMETER);
- jniThrowException(pEnv, "java/lang/IllegalArgumentException", pMessage);
- return -1;
- }
-
- for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) {
- if (timeMs <= (iIncrementedDuration +
- (pContext->pEditSettings->pClipList[i]->uiEndCutTime -
- pContext->pEditSettings->pClipList[i]->uiBeginCutTime)))
- {
- iCurrentClipIndex = i;
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() iCurrentClipIndex=%d for timeMs=%d",
- iCurrentClipIndex, timeMs);
- break;
- }
- else {
- iIncrementedDuration = iIncrementedDuration +
- (pContext->pEditSettings->pClipList[i]->uiEndCutTime -
- pContext->pEditSettings->pClipList[i]->uiBeginCutTime);
- }
- }
- }
- /* If timestamp is beyond story board duration, return*/
- if (i >= uiNumberOfClipsInStoryBoard) {
- if (timeMs == iIncrementedDuration) {
- iCurrentClipIndex = i-1;
- } else {
- return -1;
- }
- }
-
- /*+ Handle the image files here */
- if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType ==
- /*M4VIDEOEDITING_kFileType_JPG*/ M4VIDEOEDITING_kFileType_ARGB8888 ) {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", " iCurrentClipIndex %d ", iCurrentClipIndex);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- " Height = %d",
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight);
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- " Width = %d",
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth);
-
- LvGetImageThumbNail((const char *)pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->pFile,
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight,
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth,
- (M4OSA_Void **)&frameStr.pBuffer);
- tnTimeMs = (M4OSA_UInt32)timeMs;
-
- frameStr.videoRotationDegree = 0;
- } else {
- /* Handle 3gp/mp4 Clips here */
- /* get thumbnail*/
- result = ThumbnailOpen(&tnContext,
- (const M4OSA_Char*)pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->pFile, M4OSA_TRUE);
- if (result != M4NO_ERROR || tnContext == M4OSA_NULL) {
- return -1;
- }
-
- /* timeMs is relative to storyboard; in this api it shud be relative to this clip */
- if ((i >= uiNumberOfClipsInStoryBoard) &&
- (timeMs == iIncrementedDuration)) {
- tnTimeMs = pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->uiEndCutTime;
- } else {
- tnTimeMs = pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->uiBeginCutTime
- + (timeMs - iIncrementedDuration);
- }
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "video width = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoWidth);
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "video height = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoHeight);
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "current clip index = %d",iCurrentClipIndex);
-
- M4OSA_UInt32 width = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoWidth;
- M4OSA_UInt32 height = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoHeight;
-
- framesizeYuv = width * height * 1.5;
-
- pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS,
- (M4OSA_Char*)"videoEditor pixelArray");
- if (pixelArray == M4OSA_NULL) {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() malloc error");
- ThumbnailClose(tnContext);
- pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
- jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
- return -1;
- }
-
- result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray,
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoWidth,
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoHeight,
- &tnTimeMs, 0);
- if (result != M4NO_ERROR) {
- free(pixelArray);
- ThumbnailClose(tnContext);
- return -1;
- }
-
- ThumbnailClose(tnContext);
- tnContext = M4OSA_NULL;
-
-#ifdef DUMPTOFILE
- {
- M4OSA_Context fileContext;
- M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.raw";
- remove((const char *)fileName);
- M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
- M4OSA_kFileWrite|M4OSA_kFileCreate);
- M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray,
- framesizeYuv);
- M4OSA_fileWriteClose(fileContext);
- }
-#endif
-
- /**
- * Allocate output YUV planes
- */
- yuvPlane = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS,
- (M4OSA_Char*)"videoEditor_renderPreviewFrame Output plane YUV");
- if (yuvPlane == M4OSA_NULL) {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() malloc error for yuv plane");
- free(pixelArray);
- pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
- jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
- return -1;
- }
-
- yuvPlane[0].u_width = width;
- yuvPlane[0].u_height = height;
- yuvPlane[0].u_topleft = 0;
- yuvPlane[0].u_stride = width;
- yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray;
-
- yuvPlane[1].u_width = width>>1;
- yuvPlane[1].u_height = height>>1;
- yuvPlane[1].u_topleft = 0;
- yuvPlane[1].u_stride = width>>1;
- yuvPlane[1].pac_data = yuvPlane[0].pac_data
- + yuvPlane[0].u_width * yuvPlane[0].u_height;
- yuvPlane[2].u_width = (width)>>1;
- yuvPlane[2].u_height = (height)>>1;
- yuvPlane[2].u_topleft = 0;
- yuvPlane[2].u_stride = (width)>>1;
- yuvPlane[2].pac_data = yuvPlane[1].pac_data
- + yuvPlane[1].u_width * yuvPlane[1].u_height;
-
-#ifdef DUMPTOFILE
- {
- M4OSA_Context fileContext;
- M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv";
- remove((const char *)fileName);
- M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
- M4OSA_kFileWrite|M4OSA_kFileCreate);
- M4OSA_fileWriteData(fileContext,
- (M4OSA_MemAddr8) yuvPlane[0].pac_data, framesizeYuv);
- M4OSA_fileWriteClose(fileContext);
- }
-#endif
-
- /* Fill up the render structure*/
- frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data;
-
- frameStr.videoRotationDegree = pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->ClipProperties.videoRotationDegrees;
- }
-
- frameStr.timeMs = timeMs; /* timestamp on storyboard*/
- frameStr.uiSurfaceWidth =
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoWidth;
- frameStr.uiSurfaceHeight =
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoHeight;
- frameStr.uiFrameWidth =
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoWidth;
- frameStr.uiFrameHeight =
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
- ClipProperties.uiVideoHeight;
- if (pContext->pEditSettings->nbEffects > 0) {
- frameStr.bApplyEffect = M4OSA_TRUE;
- } else {
- frameStr.bApplyEffect = M4OSA_FALSE;
- }
- frameStr.clipBeginCutTime = iIncrementedDuration;
- frameStr.clipEndCutTime =
- iIncrementedDuration +
- (pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiEndCutTime -\
- pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiBeginCutTime);
-
- pContext->mPreviewController->setPreviewFrameRenderingMode(
- pContext->pEditSettings->\
- pClipList[iCurrentClipIndex]->xVSS.MediaRendering,
- pContext->pEditSettings->xVSS.outputVideoSize);
- result = pContext->mPreviewController->renderPreviewFrame(previewSurface,
- &frameStr, &currEditInfo);
-
- if (currEditInfo.overlaySettingsIndex != -1) {
- char tmpOverlayFilename[100];
- char *extPos = NULL;
- jstring tmpOverlayString;
- int tmpRenderingMode = 0;
-
- strncpy (tmpOverlayFilename,
- (const char*)pContext->pEditSettings->Effects[currEditInfo.overlaySettingsIndex].xVSS.pFramingFilePath, 99);
-
- //Change the name to png file
- extPos = strstr(tmpOverlayFilename, ".rgb");
- if (extPos != NULL) {
- *extPos = '\0';
- } else {
- ALOGE("ERROR the overlay file is incorrect");
- }
-
- strcat(tmpOverlayFilename, ".png");
-
- tmpRenderingMode = pContext->pEditSettings->pClipList[iCurrentClipIndex]->xVSS.MediaRendering;
- tmpOverlayString = pEnv->NewStringUTF(tmpOverlayFilename);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->previewFrameEditInfoId,
- tmpOverlayString, tmpRenderingMode);
-
- }
-
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
-
- free(frameStr.pBuffer);
- if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType !=
- M4VIDEOEDITING_kFileType_ARGB8888) {
- free(yuvPlane);
- }
-
- return (jint)tnTimeMs;
-}
-
-static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jstring filePath,
- jint frameWidth,
- jint frameHeight,
- jint surfaceWidth,
- jint surfaceHeight,
- jlong fromMs)
-{
- bool needToBeLoaded = true;
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs;
- M4OSA_UInt32 framesizeYuv =0;
- M4VIFI_UInt8 *pixelArray = M4OSA_NULL;
- VideoEditor_renderPreviewFrameStr frameStr;
- M4OSA_Context tnContext = M4OSA_NULL;
- const char* pMessage = NULL;
- M4VIFI_ImagePlane yuvPlane[3], rgbPlane;
-
- ManualEditContext* pContext = M4OSA_NULL;
- // Get the context.
- pContext =
- (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
- pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
-
- // Validate the mSurface parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == mSurface),
- "mSurface is null");
-
- sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
- const char *pString = pEnv->GetStringUTFChars(filePath, NULL);
- if (pString == M4OSA_NULL) {
- if (pEnv != NULL) {
- jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
- }
- }
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderMediaItemPreviewFrame() timeMs=%d", timeMs);
- /* get thumbnail*/
- result = ThumbnailOpen(&tnContext,(const M4OSA_Char*)pString, M4OSA_TRUE);
- if (result != M4NO_ERROR || tnContext == M4OSA_NULL) {
- return (jint)timeMs;
- }
-
- framesizeYuv = ((frameWidth)*(frameHeight)*1.5);
-
- pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS,\
- (M4OSA_Char*)"videoEditor pixelArray");
- if (pixelArray == M4OSA_NULL) {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_renderPreviewFrame() malloc error");
- ThumbnailClose(tnContext);
- pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
- jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
- return (jint)timeMs;
- }
-
- result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray,
- frameWidth,
- frameHeight, &timeMs, 0);
- if (result != M4NO_ERROR) {
- free(pixelArray);
- ThumbnailClose(tnContext);
- return (jint)fromMs;
- }
-
-#ifdef DUMPTOFILESYSTEM
- {
- M4OSA_Context fileContext;
- M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.rgb";
- M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
- M4OSA_kFileWrite|M4OSA_kFileCreate);
- M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray,
- framesizeRgb);
- M4OSA_fileWriteClose(fileContext);
- }
-#endif
-
- yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray;
- yuvPlane[0].u_height = frameHeight;
- yuvPlane[0].u_width = frameWidth;
- yuvPlane[0].u_stride = yuvPlane[0].u_width;
- yuvPlane[0].u_topleft = 0;
-
- yuvPlane[1].u_height = frameHeight/2;
- yuvPlane[1].u_width = frameWidth/2;
- yuvPlane[1].u_stride = yuvPlane[1].u_width;
- yuvPlane[1].u_topleft = 0;
- yuvPlane[1].pac_data = yuvPlane[0].pac_data
- + yuvPlane[0].u_width*yuvPlane[0].u_height;
-
- yuvPlane[2].u_height = frameHeight/2;
- yuvPlane[2].u_width = frameWidth/2;
- yuvPlane[2].u_stride = yuvPlane[2].u_width;
- yuvPlane[2].u_topleft = 0;
- yuvPlane[2].pac_data = yuvPlane[0].pac_data
- + yuvPlane[0].u_width*yuvPlane[0].u_height + \
- (yuvPlane[0].u_width/2)*(yuvPlane[0].u_height/2);
-#ifdef DUMPTOFILESYSTEM
- {
- M4OSA_Context fileContext;
- M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv";
- M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
- M4OSA_kFileWrite|M4OSA_kFileCreate);
- M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) yuvPlane[0].pac_data,
- framesizeYuv);
- M4OSA_fileWriteClose(fileContext);
- }
-#endif
-
- /* Fill up the render structure*/
- frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data;
- frameStr.timeMs = timeMs; /* timestamp on storyboard*/
- frameStr.uiSurfaceWidth = frameWidth;
- frameStr.uiSurfaceHeight = frameHeight;
- frameStr.uiFrameWidth = frameWidth;
- frameStr.uiFrameHeight = frameHeight;
- frameStr.bApplyEffect = M4OSA_FALSE;
- // clip begin cuttime and end cuttime set to 0
- // as its only required when effect needs to be applied while rendering
- frameStr.clipBeginCutTime = 0;
- frameStr.clipEndCutTime = 0;
-
- /* pContext->mPreviewController->setPreviewFrameRenderingMode(M4xVSS_kBlackBorders,
- (M4VIDEOEDITING_VideoFrameSize)(M4VIDEOEDITING_kHD960+1));*/
- result
- = pContext->mPreviewController->renderPreviewFrame(previewSurface,&frameStr, NULL);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
-
- /* free the pixelArray and yuvPlane[0].pac_data */
- free(yuvPlane[0].pac_data);
-
- ThumbnailClose(tnContext);
-
- if (pString != NULL) {
- pEnv->ReleaseStringUTFChars(filePath, pString);
- }
-
- return (jint)timeMs;
-}
-
-jint videoEditor_generateAudioRawFile( JNIEnv* pEnv,
- jobject thiz,
- jstring infilePath,
- jstring pcmfilePath)
-{
- M4OSA_ERR result = M4NO_ERROR;
- bool loaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
-
-
-
- const char *pInputFile = pEnv->GetStringUTFChars(infilePath, NULL);
- if (pInputFile == M4OSA_NULL) {
- if (pEnv != NULL) {
- jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
- }
- }
-
- const char *pStringOutPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL);
- if (pStringOutPCMFilePath == M4OSA_NULL) {
- if (pEnv != NULL) {
- jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
- }
- }
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR", "videoEditor_generateAudioRawFile infilePath %s",
- pInputFile);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
- "VIDEO_EDITOR", "videoEditor_generateAudioRawFile pcmfilePath %s",
- pStringOutPCMFilePath);
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
- result = videoEditor_generateAudio( pEnv, pContext, (M4OSA_Char*)pInputFile,
- (M4OSA_Char*)pStringOutPCMFilePath);
-
- if (pInputFile != NULL) {
- pEnv->ReleaseStringUTFChars(infilePath, pInputFile);
- }
- if (pStringOutPCMFilePath != NULL) {
- pEnv->ReleaseStringUTFChars(pcmfilePath, pStringOutPCMFilePath);
- }
-
- return (jint)result;
-}
-
-M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext,
- M4OSA_Char* infilePath,
- M4OSA_Char* pcmfilePath )
-{
- bool needToBeLoaded = true;
- M4OSA_ERR result = M4NO_ERROR;
- M4MCS_Context mcsContext = M4OSA_NULL;
- M4OSA_Char* pInputFile = M4OSA_NULL;
- M4OSA_Char* pOutputFile = M4OSA_NULL;
- M4OSA_Char* pTempPath = M4OSA_NULL;
- M4MCS_OutputParams* pOutputParams = M4OSA_NULL;
- M4MCS_EncodingParams* pEncodingParams = M4OSA_NULL;
- M4OSA_Int32 pInputFileType = 0;
- M4OSA_UInt8 threadProgress = 0;
- M4OSA_Char* pTemp3gpFilePath = M4OSA_NULL;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio()");
-
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == pContext),
- "ManualEditContext is null");
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_init()");
-
- pOutputParams = (M4MCS_OutputParams *)M4OSA_32bitAlignedMalloc(
- sizeof(M4MCS_OutputParams),0x00,
- (M4OSA_Char *)"M4MCS_OutputParams");
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pOutputParams),
- "not initialized");
- if (needToBeLoaded == false) {
- return M4ERR_ALLOC;
- }
-
- pEncodingParams = (M4MCS_EncodingParams *)M4OSA_32bitAlignedMalloc(
- sizeof(M4MCS_EncodingParams),0x00,
- (M4OSA_Char *)"M4MCS_EncodingParams");
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pEncodingParams),
- "not initialized");
- if (needToBeLoaded == false) {
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return M4ERR_ALLOC;
- }
-
- // Initialize the MCS library.
- result = M4MCS_init(&mcsContext, pContext->initParams.pFileReadPtr,
- pContext->initParams.pFileWritePtr);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,\
- (M4NO_ERROR != result), result);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == mcsContext),
- "not initialized");
- if(needToBeLoaded == false) {
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
-
- // generate the path for temp 3gp output file
- pTemp3gpFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc (
- (strlen((const char*)pContext->initParams.pTempPath)
- + strlen((const char*)TEMP_MCS_OUT_FILE_PATH)) + 1 /* for null termination */ , 0x0,
- (M4OSA_Char*)"Malloc for temp 3gp file");
- if (pTemp3gpFilePath != M4OSA_NULL)
- {
- memset((void *)pTemp3gpFilePath ,0,
- strlen((const char*)pContext->initParams.pTempPath)
- + strlen((const char*)TEMP_MCS_OUT_FILE_PATH) + 1);
- strncat((char *)pTemp3gpFilePath,
- (const char *)pContext->initParams.pTempPath ,
- (size_t) ((M4OSA_Char*)pContext->initParams.pTempPath));
- strncat((char *)pTemp3gpFilePath , (const char *)TEMP_MCS_OUT_FILE_PATH,
- (size_t)strlen ((const char*)TEMP_MCS_OUT_FILE_PATH));
- }
- else {
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return M4ERR_ALLOC;
- }
-
- pInputFile = (M4OSA_Char *) infilePath; //pContext->mAudioSettings->pFile;
- //Delete this file later
- pOutputFile = (M4OSA_Char *) pTemp3gpFilePath;
- // Temp folder path for VSS use = ProjectPath
- pTempPath = (M4OSA_Char *) pContext->initParams.pTempPath;
- pInputFileType = (M4VIDEOEDITING_FileType)pContext->mAudioSettings->fileType;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "TEMP_MCS_OUT_FILE_PATH len %d",
- strlen ((const char*)TEMP_MCS_OUT_FILE_PATH));
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pTemp3gpFilePath %s",
- pOutputFile);
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_open()");
-
- result = M4MCS_open(mcsContext, pInputFile,
- (M4VIDEOEDITING_FileType)pInputFileType,
- pOutputFile, pTempPath);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if(needToBeLoaded == false) {
- free(pTemp3gpFilePath);
- pTemp3gpFilePath = M4OSA_NULL;
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
-
- pOutputParams->OutputFileType
- = (M4VIDEOEDITING_FileType)M4VIDEOEDITING_kFileType_3GPP;
- // Set the video format.
- pOutputParams->OutputVideoFormat =
- (M4VIDEOEDITING_VideoFormat)M4VIDEOEDITING_kNoneVideo;//M4VIDEOEDITING_kNoneVideo;
- pOutputParams->outputVideoProfile = 1;
- pOutputParams->outputVideoLevel = 1;
- // Set the frame size.
- pOutputParams->OutputVideoFrameSize
- = (M4VIDEOEDITING_VideoFrameSize)M4VIDEOEDITING_kQCIF;
- // Set the frame rate.
- pOutputParams->OutputVideoFrameRate
- = (M4VIDEOEDITING_VideoFramerate)M4VIDEOEDITING_k5_FPS;
-
- // Set the audio format.
- pOutputParams->OutputAudioFormat
- = (M4VIDEOEDITING_AudioFormat)M4VIDEOEDITING_kAAC;
- // Set the audio sampling frequency.
- pOutputParams->OutputAudioSamplingFrequency =
- (M4VIDEOEDITING_AudioSamplingFrequency)M4VIDEOEDITING_k32000_ASF;
- // Set the audio mono.
- pOutputParams->bAudioMono = false;
- // Set the pcm file; null for now.
- pOutputParams->pOutputPCMfile = (M4OSA_Char *)pcmfilePath;
- //(M4OSA_Char *)"/sdcard/Output/AudioPcm.pcm";
- // Set the audio sampling frequency.
- pOutputParams->MediaRendering = (M4MCS_MediaRendering)M4MCS_kCropping;
- // new params after integrating MCS 2.0
- // Set the number of audio effects; 0 for now.
- pOutputParams->nbEffects = 0;
- // Set the audio effect; null for now.
- pOutputParams->pEffects = NULL;
- // Set the audio effect; null for now.
- pOutputParams->bDiscardExif = M4OSA_FALSE;
- // Set the audio effect; null for now.
- pOutputParams->bAdjustOrientation = M4OSA_FALSE;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_setOutputParams()");
- result = M4MCS_setOutputParams(mcsContext, pOutputParams);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if (needToBeLoaded == false) {
- free(pTemp3gpFilePath);
- pTemp3gpFilePath = M4OSA_NULL;
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
- // Set the video bitrate.
- pEncodingParams->OutputVideoBitrate =
- (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_kUndefinedBitrate;
- // Set the audio bitrate.
- pEncodingParams->OutputAudioBitrate
- = (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_k128_KBPS;
- // Set the end cut time in milliseconds.
- pEncodingParams->BeginCutTime = 0;
- // Set the end cut time in milliseconds.
- pEncodingParams->EndCutTime = 0;
- // Set the output file size in bytes.
- pEncodingParams->OutputFileSize = 0;
- // Set video time scale.
- pEncodingParams->OutputVideoTimescale = 0;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "M4MCS_setEncodingParams()");
- result = M4MCS_setEncodingParams(mcsContext, pEncodingParams);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if (needToBeLoaded == false) {
- free(pTemp3gpFilePath);
- pTemp3gpFilePath = M4OSA_NULL;
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "M4MCS_checkParamsAndStart()");
- result = M4MCS_checkParamsAndStart(mcsContext);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if (needToBeLoaded == false) {
- free(pTemp3gpFilePath);
- pTemp3gpFilePath = M4OSA_NULL;
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_step()");
-
- /*+ PROGRESS CB */
- M4OSA_UInt8 curProgress = 0;
- int lastProgress = 0;
-
- ALOGV("LVME_generateAudio Current progress is =%d", curProgress);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onProgressUpdateMethodId, 1/*task status*/,
- curProgress/*progress*/);
- do {
- result = M4MCS_step(mcsContext, &curProgress);
-
- if (result != M4NO_ERROR) {
- ALOGV("LVME_generateAudio M4MCS_step returned 0x%x",result);
-
- if (result == M4MCS_WAR_TRANSCODING_DONE) {
- ALOGV("LVME_generateAudio MCS process ended");
-
- // Send a progress notification.
- curProgress = 100;
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onProgressUpdateMethodId, 1/*task status*/,
- curProgress);
- ALOGV("LVME_generateAudio Current progress is =%d", curProgress);
- }
- } else {
- // Send a progress notification if needed
- if (curProgress != lastProgress) {
- lastProgress = curProgress;
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onProgressUpdateMethodId, 0/*task status*/,
- curProgress/*progress*/);
- ALOGV("LVME_generateAudio Current progress is =%d",curProgress);
- }
- }
- } while (result == M4NO_ERROR);
- /*- PROGRESS CB */
-
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4MCS_WAR_TRANSCODING_DONE != result), result);
- if (needToBeLoaded == false) {
- free(pTemp3gpFilePath);
- pTemp3gpFilePath = M4OSA_NULL;
- M4MCS_abort(mcsContext);
- free(pOutputParams);
- pOutputParams = M4OSA_NULL;
- free(pEncodingParams);
- pEncodingParams = M4OSA_NULL;
- return result;
- }
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_abort()");
- result = M4MCS_abort(mcsContext);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
-
- //pContext->mAudioSettings->pFile = pOutputParams->pOutputPCMfile;
- remove((const char *) pTemp3gpFilePath);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio() EXIT ");
-
- if (pTemp3gpFilePath != M4OSA_NULL) {
- free(pTemp3gpFilePath);
- }
- if (pOutputParams != M4OSA_NULL) {
- free(pOutputParams);
- }
- if(pEncodingParams != M4OSA_NULL) {
- free(pEncodingParams);
- }
- return result;
-}
-
-static int removeAlphafromRGB8888 (
- M4OSA_Char* pFramingFilePath,
- M4xVSS_FramingStruct *pFramingCtx)
-{
- M4OSA_UInt32 frameSize_argb = (pFramingCtx->width * pFramingCtx->height * 4); // aRGB data
- M4OSA_Context lImageFileFp = M4OSA_NULL;
- M4OSA_ERR err = M4NO_ERROR;
-
- ALOGV("removeAlphafromRGB8888: width %d", pFramingCtx->width);
-
- M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, M4VS, (M4OSA_Char*)"Image argb data");
- if (pTmpData == M4OSA_NULL) {
- ALOGE("Failed to allocate memory for Image clip");
- return M4ERR_ALLOC;
- }
-
- /** Read the argb data from the passed file. */
- M4OSA_ERR lerr = M4OSA_fileReadOpen(&lImageFileFp, (M4OSA_Void *) pFramingFilePath, M4OSA_kFileRead);
-
-
- if ((lerr != M4NO_ERROR) || (lImageFileFp == M4OSA_NULL))
- {
- ALOGE("removeAlphafromRGB8888: Can not open the file ");
- free(pTmpData);
- return M4ERR_FILE_NOT_FOUND;
- }
-
-
- lerr = M4OSA_fileReadData(lImageFileFp, (M4OSA_MemAddr8)pTmpData, &frameSize_argb);
- if (lerr != M4NO_ERROR)
- {
- ALOGE("removeAlphafromRGB8888: can not read the data ");
- M4OSA_fileReadClose(lImageFileFp);
- free(pTmpData);
- return lerr;
- }
- M4OSA_fileReadClose(lImageFileFp);
-
- M4OSA_UInt32 frameSize = (pFramingCtx->width * pFramingCtx->height * 3); //Size of RGB 888 data.
-
- pFramingCtx->FramingRgb = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(
- sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"Image clip RGB888 data");
- pFramingCtx->FramingRgb->pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(
- frameSize, M4VS, (M4OSA_Char*)"Image clip RGB888 data");
-
- if (pFramingCtx->FramingRgb == M4OSA_NULL)
- {
- ALOGE("Failed to allocate memory for Image clip");
- free(pTmpData);
- return M4ERR_ALLOC;
- }
-
- /** Remove the alpha channel */
- for (size_t i = 0, j = 0; i < frameSize_argb; i++) {
- if ((i % 4) == 0) continue;
- pFramingCtx->FramingRgb->pac_data[j] = pTmpData[i];
- j++;
- }
- free(pTmpData);
- return M4NO_ERROR;
-}
-
-static void
-videoEditor_populateSettings(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings,
- jobject object,
- jobject audioSettingObject)
-{
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_populateSettings()");
-
- bool needToBeLoaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
- jstring strPath = M4OSA_NULL;
- jstring strPCMPath = M4OSA_NULL;
- jobjectArray propertiesClipsArray = M4OSA_NULL;
- jobject properties = M4OSA_NULL;
- jint* bitmapArray = M4OSA_NULL;
- jobjectArray effectSettingsArray = M4OSA_NULL;
- jobject effectSettings = M4OSA_NULL;
- jintArray pixelArray = M4OSA_NULL;
- int width = 0;
- int height = 0;
- int nbOverlays = 0;
- int i,j = 0;
- int *pOverlayIndex = M4OSA_NULL;
- M4OSA_Char* pTempChar = M4OSA_NULL;
-
- // Validate the settings parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == settings),
- "settings is null");
- // Get the context.
- pContext =
- (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
- jclass mPreviewClipPropClazz = pEnv->FindClass(PREVIEW_PROPERTIES_CLASS_NAME);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == mPreviewClipPropClazz),
- "not initialized");
-
- jfieldID fid = pEnv->GetFieldID(mPreviewClipPropClazz,"clipProperties",
- "[L"PROPERTIES_CLASS_NAME";" );
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == fid),
- "not initialized");
-
- propertiesClipsArray = (jobjectArray)pEnv->GetObjectField(object, fid);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == propertiesClipsArray),
- "not initialized");
-
- jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == engineClass),
- "not initialized");
-
- pContext->onPreviewProgressUpdateMethodId = pEnv->GetMethodID(engineClass,
- "onPreviewProgressUpdate", "(IZZLjava/lang/String;II)V");
- // Check if the context is valid (required because the context is dereferenced).
- if (needToBeLoaded) {
- // Make sure that we are in a correct state.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (pContext->state != ManualEditState_INITIALIZED),
- "settings already loaded");
- if (needToBeLoaded) {
- // Retrieve the edit settings.
- if (pContext->pEditSettings != M4OSA_NULL) {
- videoEditClasses_freeEditSettings(&pContext->pEditSettings);
- pContext->pEditSettings = M4OSA_NULL;
- }
- videoEditClasses_getEditSettings(&needToBeLoaded, pEnv,
- settings, &pContext->pEditSettings,false);
- }
- }
-
- if (needToBeLoaded == false) {
- j = 0;
- while (j < pContext->pEditSettings->nbEffects)
- {
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
- free(pContext->pEditSettings->\
- Effects[j].xVSS.pFramingBuffer);
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
- }
- }
- j++;
- }
- return;
- }
-
- M4OSA_TRACE1_0("videoEditorC_getEditSettings done");
-
- pContext->previewFrameEditInfoId = pEnv->GetMethodID(engineClass,
- "previewFrameEditInfo", "(Ljava/lang/String;I)V");
-
- if ( pContext->pEditSettings != NULL )
- {
- // Check if the edit settings could be retrieved.
- jclass mEditClazz = pEnv->FindClass(EDIT_SETTINGS_CLASS_NAME);
- if(mEditClazz == M4OSA_NULL)
- {
- M4OSA_TRACE1_0("cannot find object field for mEditClazz");
- goto videoEditor_populateSettings_cleanup;
- }
- jclass mEffectsClazz = pEnv->FindClass(EFFECT_SETTINGS_CLASS_NAME);
- if(mEffectsClazz == M4OSA_NULL)
- {
- M4OSA_TRACE1_0("cannot find object field for mEffectsClazz");
- goto videoEditor_populateSettings_cleanup;
- }
- fid = pEnv->GetFieldID(mEditClazz,"effectSettingsArray", "[L"EFFECT_SETTINGS_CLASS_NAME";" );
- if(fid == M4OSA_NULL)
- {
- M4OSA_TRACE1_0("cannot find field for effectSettingsArray Array");
- goto videoEditor_populateSettings_cleanup;
- }
- effectSettingsArray = (jobjectArray)pEnv->GetObjectField(settings, fid);
- if(effectSettingsArray == M4OSA_NULL)
- {
- M4OSA_TRACE1_0("cannot find object field for effectSettingsArray");
- goto videoEditor_populateSettings_cleanup;
- }
-
- //int overlayIndex[pContext->pEditSettings->nbEffects];
- if (pContext->pEditSettings->nbEffects > 0)
- {
- pOverlayIndex
- = (int*) M4OSA_32bitAlignedMalloc(pContext->pEditSettings->nbEffects * sizeof(int), 0,
- (M4OSA_Char*)"pOverlayIndex");
- if (pOverlayIndex == M4OSA_NULL) {
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- M4OSA_TRUE, M4ERR_ALLOC);
- goto videoEditor_populateSettings_cleanup;
- }
- }
-
- i = 0;
- j = 0;
- M4OSA_TRACE1_1("no of effects = %d",pContext->pEditSettings->nbEffects);
- while (j < pContext->pEditSettings->nbEffects)
- {
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL)
- {
- pOverlayIndex[nbOverlays] = j;
-
- M4xVSS_FramingStruct *aFramingCtx = M4OSA_NULL;
- aFramingCtx
- = (M4xVSS_FramingStruct*)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS,
- (M4OSA_Char*)"M4xVSS_internalDecodeGIF: Context of the framing effect");
- if (aFramingCtx == M4OSA_NULL)
- {
- M4OSA_TRACE1_0("Allocation error in videoEditor_populateSettings");
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- M4OSA_TRUE, M4ERR_ALLOC);
- goto videoEditor_populateSettings_cleanup;
- }
-
- aFramingCtx->pCurrent = M4OSA_NULL; /* Only used by the first element of the chain */
- aFramingCtx->previousClipTime = -1;
- aFramingCtx->FramingYuv = M4OSA_NULL;
- aFramingCtx->FramingRgb = M4OSA_NULL;
- aFramingCtx->topleft_x
- = pContext->pEditSettings->Effects[j].xVSS.topleft_x;
- aFramingCtx->topleft_y
- = pContext->pEditSettings->Effects[j].xVSS.topleft_y;
-
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_width %d",
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_height() %d",
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF rgbType() %d",
- pContext->pEditSettings->Effects[j].xVSS.rgbType);
-
- aFramingCtx->width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width;
- aFramingCtx->height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
-
- result = M4xVSS_internalConvertARGB888toYUV420_FrammingEffect(pContext->engineContext,
- &(pContext->pEditSettings->Effects[j]),aFramingCtx,
- pContext->pEditSettings->Effects[j].xVSS.framingScaledSize);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if (needToBeLoaded == false) {
- M4OSA_TRACE1_1("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect returned 0x%x", result);
- if (aFramingCtx != M4OSA_NULL) {
- free(aFramingCtx);
- aFramingCtx = M4OSA_NULL;
- }
- goto videoEditor_populateSettings_cleanup;
- }
-
- //framing buffers are resized to fit the output video resolution.
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width =
- aFramingCtx->FramingRgb->u_width;
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height =
- aFramingCtx->FramingRgb->u_height;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->width = %d",
- aFramingCtx->FramingRgb->u_width);
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->height = %d",
- aFramingCtx->FramingRgb->u_height);
-
-
- width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width;
- height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
-
- //RGB 565
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_stride = width * 2;
-
- //for RGB565
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_topleft = 0;
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data =
- (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(width*height*2,
- 0x00,(M4OSA_Char *)"pac_data buffer");
-
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data == M4OSA_NULL) {
- M4OSA_TRACE1_0("Failed to allocate memory for framing buffer");
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- M4OSA_TRUE, M4ERR_ALLOC);
- goto videoEditor_populateSettings_cleanup;
- }
-
- memcpy((void *)&pContext->pEditSettings->\
- Effects[j].xVSS.pFramingBuffer->\
- pac_data[0],(void *)&aFramingCtx->FramingRgb->pac_data[0],(width*height*2));
-
- //As of now rgb type is 565
- pContext->pEditSettings->Effects[j].xVSS.rgbType =
- (M4VSS3GPP_RGBType) M4VSS3GPP_kRGB565;
-
- if (aFramingCtx->FramingYuv != M4OSA_NULL )
- {
- if (aFramingCtx->FramingYuv[0].pac_data != M4OSA_NULL) {
- free(aFramingCtx->FramingYuv[0].pac_data);
- aFramingCtx->FramingYuv[0].pac_data = M4OSA_NULL;
- }
- if (aFramingCtx->FramingYuv[1].pac_data != M4OSA_NULL) {
- free(aFramingCtx->FramingYuv[1].pac_data);
- aFramingCtx->FramingYuv[1].pac_data = M4OSA_NULL;
- }
- if (aFramingCtx->FramingYuv[2].pac_data != M4OSA_NULL) {
- free(aFramingCtx->FramingYuv[2].pac_data);
- aFramingCtx->FramingYuv[2].pac_data = M4OSA_NULL;
- }
-
- free(aFramingCtx->FramingYuv);
- aFramingCtx->FramingYuv = M4OSA_NULL;
- }
- if (aFramingCtx->FramingRgb->pac_data != M4OSA_NULL) {
- free(aFramingCtx->FramingRgb->pac_data);
- aFramingCtx->FramingRgb->pac_data = M4OSA_NULL;
- }
- if (aFramingCtx->FramingRgb != M4OSA_NULL) {
- free(aFramingCtx->FramingRgb);
- aFramingCtx->FramingRgb = M4OSA_NULL;
- }
- if (aFramingCtx != M4OSA_NULL) {
- free(aFramingCtx);
- aFramingCtx = M4OSA_NULL;
- }
- nbOverlays++;
- }
- j++;
- }
-
- // Check if the edit settings could be retrieved.
- M4OSA_TRACE1_1("total clips are = %d",pContext->pEditSettings->uiClipNumber);
- for (i = 0; i < pContext->pEditSettings->uiClipNumber; i++) {
- M4OSA_TRACE1_1("clip no = %d",i);
- properties = pEnv->GetObjectArrayElement(propertiesClipsArray, i);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == properties),
- "not initialized");
- if (needToBeLoaded) {
- getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
- pEnv->DeleteLocalRef(properties);
- } else {
- pEnv->DeleteLocalRef(properties);
- goto videoEditor_populateSettings_cleanup;
- }
- }
-
- if (needToBeLoaded) {
- // Log the edit settings.
- VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings);
- }
- }
- /* free previous allocations , if any */
- if (pContext->mAudioSettings != M4OSA_NULL) {
- if (pContext->mAudioSettings->pFile != NULL) {
- free(pContext->mAudioSettings->pFile);
- pContext->mAudioSettings->pFile = M4OSA_NULL;
- }
- if (pContext->mAudioSettings->pPCMFilePath != NULL) {
- free(pContext->mAudioSettings->pPCMFilePath);
- pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
- }
- }
-
- if (audioSettingObject != M4OSA_NULL) {
- jclass audioSettingClazz = pEnv->FindClass(AUDIO_SETTINGS_CLASS_NAME);
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == audioSettingClazz),
- "not initialized");
-
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mAudioSettings),
- "not initialized");
-
- if (needToBeLoaded == false) {
- goto videoEditor_populateSettings_cleanup;
- }
-
- fid = pEnv->GetFieldID(audioSettingClazz,"bRemoveOriginal","Z");
- pContext->mAudioSettings->bRemoveOriginal =
- pEnv->GetBooleanField(audioSettingObject,fid);
- M4OSA_TRACE1_1("bRemoveOriginal = %d",pContext->mAudioSettings->bRemoveOriginal);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"channels","I");
- pContext->mAudioSettings->uiNbChannels = pEnv->GetIntField(audioSettingObject,fid);
- M4OSA_TRACE1_1("uiNbChannels = %d",pContext->mAudioSettings->uiNbChannels);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"Fs","I");
- pContext->mAudioSettings->uiSamplingFrequency = pEnv->GetIntField(audioSettingObject,fid);
- M4OSA_TRACE1_1("uiSamplingFrequency = %d",pContext->mAudioSettings->uiSamplingFrequency);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"ExtendedFs","I");
- pContext->mAudioSettings->uiExtendedSamplingFrequency =
- pEnv->GetIntField(audioSettingObject,fid);
- M4OSA_TRACE1_1("uiExtendedSamplingFrequency = %d",
- pContext->mAudioSettings->uiExtendedSamplingFrequency);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"startMs","J");
- pContext->mAudioSettings->uiAddCts
- = pEnv->GetLongField(audioSettingObject,fid);
- M4OSA_TRACE1_1("uiAddCts = %d",pContext->mAudioSettings->uiAddCts);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"volume","I");
- pContext->mAudioSettings->uiAddVolume
- = pEnv->GetIntField(audioSettingObject,fid);
- M4OSA_TRACE1_1("uiAddVolume = %d",pContext->mAudioSettings->uiAddVolume);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"loop","Z");
- pContext->mAudioSettings->bLoop
- = pEnv->GetBooleanField(audioSettingObject,fid);
- M4OSA_TRACE1_1("bLoop = %d",pContext->mAudioSettings->bLoop);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"beginCutTime","J");
- pContext->mAudioSettings->beginCutMs
- = pEnv->GetLongField(audioSettingObject,fid);
- M4OSA_TRACE1_1("begin cut time = %d",pContext->mAudioSettings->beginCutMs);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"endCutTime","J");
- pContext->mAudioSettings->endCutMs
- = pEnv->GetLongField(audioSettingObject,fid);
- M4OSA_TRACE1_1("end cut time = %d",pContext->mAudioSettings->endCutMs);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"fileType","I");
- pContext->mAudioSettings->fileType
- = pEnv->GetIntField(audioSettingObject,fid);
- M4OSA_TRACE1_1("fileType = %d",pContext->mAudioSettings->fileType);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"pFile","Ljava/lang/String;");
- strPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
- pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPath, M4OSA_NULL);
- if (pTempChar != NULL) {
- pContext->mAudioSettings->pFile = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(
- (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
- (M4OSA_Char*)"strPath allocation " );
- if (pContext->mAudioSettings->pFile != M4OSA_NULL) {
- memcpy((void *)pContext->mAudioSettings->pFile ,
- (void *)pTempChar , strlen((const char*)pTempChar));
- ((M4OSA_Int8 *)(pContext->mAudioSettings->pFile))[strlen((const char*)pTempChar)] = '\0';
- pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
- } else {
- pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "regenerateAudio() Malloc failed for pContext->mAudioSettings->pFile ");
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- M4OSA_TRUE, M4ERR_ALLOC);
- goto videoEditor_populateSettings_cleanup;
- }
- }
- M4OSA_TRACE1_1("file name = %s",pContext->mAudioSettings->pFile);
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio() file name = %s",\
- pContext->mAudioSettings->pFile);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"pcmFilePath","Ljava/lang/String;");
- strPCMPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
- pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPCMPath, M4OSA_NULL);
- if (pTempChar != NULL) {
- pContext->mAudioSettings->pPCMFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(
- (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
- (M4OSA_Char*)"strPCMPath allocation " );
- if (pContext->mAudioSettings->pPCMFilePath != M4OSA_NULL) {
- memcpy((void *)pContext->mAudioSettings->pPCMFilePath ,
- (void *)pTempChar , strlen((const char*)pTempChar));
- ((M4OSA_Int8 *)(pContext->mAudioSettings->pPCMFilePath))[strlen((const char*)pTempChar)] = '\0';
- pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
- } else {
- pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "regenerateAudio() Malloc failed for pContext->mAudioSettings->pPCMFilePath ");
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- M4OSA_TRUE, M4ERR_ALLOC);
- goto videoEditor_populateSettings_cleanup;
- }
- }
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "pPCMFilePath -- %s ",\
- pContext->mAudioSettings->pPCMFilePath);
-
- fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
- bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio -- %d ",\
- regenerateAudio);
-
- if (regenerateAudio) {
- M4OSA_TRACE1_0("Calling Generate Audio now");
- result = videoEditor_generateAudio(pEnv,
- pContext,
- (M4OSA_Char*)pContext->mAudioSettings->pFile,
- (M4OSA_Char*)pContext->mAudioSettings->pPCMFilePath);
-
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- if (needToBeLoaded == false) {
- goto videoEditor_populateSettings_cleanup;
- }
-
- regenerateAudio = false;
- pEnv->SetBooleanField(thiz,fid,regenerateAudio);
- }
-
- /* Audio mix and duck */
- fid = pEnv->GetFieldID(audioSettingClazz,"ducking_threshold","I");
- pContext->mAudioSettings->uiInDucking_threshold
- = pEnv->GetIntField(audioSettingObject,fid);
-
- M4OSA_TRACE1_1("ducking threshold = %d",
- pContext->mAudioSettings->uiInDucking_threshold);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"ducking_lowVolume","I");
- pContext->mAudioSettings->uiInDucking_lowVolume
- = pEnv->GetIntField(audioSettingObject,fid);
-
- M4OSA_TRACE1_1("ducking lowVolume = %d",
- pContext->mAudioSettings->uiInDucking_lowVolume);
-
- fid = pEnv->GetFieldID(audioSettingClazz,"bInDucking_enable","Z");
- pContext->mAudioSettings->bInDucking_enable
- = pEnv->GetBooleanField(audioSettingObject,fid);
- M4OSA_TRACE1_1("ducking lowVolume = %d",
- pContext->mAudioSettings->bInDucking_enable);
-
- } else {
- if (pContext->mAudioSettings != M4OSA_NULL) {
- pContext->mAudioSettings->pFile = M4OSA_NULL;
- pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
- pContext->mAudioSettings->bRemoveOriginal = 0;
- pContext->mAudioSettings->uiNbChannels = 0;
- pContext->mAudioSettings->uiSamplingFrequency = 0;
- pContext->mAudioSettings->uiExtendedSamplingFrequency = 0;
- pContext->mAudioSettings->uiAddCts = 0;
- pContext->mAudioSettings->uiAddVolume = 0;
- pContext->mAudioSettings->beginCutMs = 0;
- pContext->mAudioSettings->endCutMs = 0;
- pContext->mAudioSettings->fileType = 0;
- pContext->mAudioSettings->bLoop = 0;
- pContext->mAudioSettings->uiInDucking_lowVolume = 0;
- pContext->mAudioSettings->bInDucking_enable = 0;
- pContext->mAudioSettings->uiBTChannelCount = 0;
- pContext->mAudioSettings->uiInDucking_threshold = 0;
-
- fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
- bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
- if (!regenerateAudio) {
- regenerateAudio = true;
- pEnv->SetBooleanField(thiz,fid,regenerateAudio);
- }
- }
- }
-
- if (pContext->pEditSettings != NULL)
- {
- result = pContext->mPreviewController->loadEditSettings(pContext->pEditSettings,
- pContext->mAudioSettings);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
-
- if (needToBeLoaded) {
- pContext->mPreviewController->setJniCallback((void*)pContext,
- (jni_progress_callback_fct)jniPreviewProgressCallback);
- }
- }
-
-videoEditor_populateSettings_cleanup:
- j = 0;
- while (j < nbOverlays)
- {
- if (pContext->pEditSettings->Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data != \
- M4OSA_NULL) {
- free(pContext->pEditSettings->\
- Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data);
- pContext->pEditSettings->\
- Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data = M4OSA_NULL;
- }
- j++;
- }
-
- j = 0;
- while (j < pContext->pEditSettings->nbEffects)
- {
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
- if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
- free(pContext->pEditSettings->\
- Effects[j].xVSS.pFramingBuffer);
- pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
- }
- }
- j++;
- }
-
- if (pOverlayIndex != M4OSA_NULL)
- {
- free(pOverlayIndex);
- pOverlayIndex = M4OSA_NULL;
- }
- return;
-}
-
-static void
-videoEditor_startPreview(
- JNIEnv* pEnv,
- jobject thiz,
- jobject mSurface,
- jlong fromMs,
- jlong toMs,
- jint callbackInterval,
- jboolean loop)
-{
- bool needToBeLoaded = true;
- M4OSA_ERR result = M4NO_ERROR;
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_startPreview()");
-
- ManualEditContext* pContext = M4OSA_NULL;
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mAudioSettings),
- "not initialized");
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
-
- // Validate the mSurface parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == mSurface),
- "mSurface is null");
-
- sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
- // Validate the mSurface's mNativeSurface field
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (NULL == previewSurface.get()),
- "mNativeSurface is null");
-
- result = pContext->mPreviewController->setSurface(previewSurface);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
- (M4NO_ERROR != result), result);
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "fromMs=%ld, toMs=%ld",
- (M4OSA_UInt32)fromMs, (M4OSA_Int32)toMs);
-
- result = pContext->mPreviewController->startPreview((M4OSA_UInt32)fromMs,
- (M4OSA_Int32)toMs,
- (M4OSA_UInt16)callbackInterval,
- (M4OSA_Bool)loop);
- videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, (M4NO_ERROR != result), result);
-}
-
-
-static jobject
-videoEditor_getProperties(
- JNIEnv* pEnv,
- jobject thiz,
- jstring file)
-{
- jobject object = M4OSA_NULL;
- jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME);
- jfieldID fid;
- bool needToBeLoaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
- int profile = 0;
- int level = 0;
- int videoFormat = 0;
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == clazz),
- "not initialized");
-
- object = videoEditProp_getProperties(pEnv,thiz,file);
-
- if (object != M4OSA_NULL) {
- fid = pEnv->GetFieldID(clazz,"profile","I");
- profile = pEnv->GetIntField(object,fid);
- fid = pEnv->GetFieldID(clazz,"level","I");
- level = pEnv->GetIntField(object,fid);
- fid = pEnv->GetFieldID(clazz,"videoFormat","I");
- videoFormat = pEnv->GetIntField(object,fid);
-
- result = checkClipVideoProfileAndLevel(pContext->decoders, videoFormat, profile, level);
-
- fid = pEnv->GetFieldID(clazz,"profileSupported","Z");
- if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE == result) {
- pEnv->SetBooleanField(object,fid,false);
- }
-
- fid = pEnv->GetFieldID(clazz,"levelSupported","Z");
- if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL == result) {
- pEnv->SetBooleanField(object,fid,false);
- }
- }
- return object;
-
-}
-static jint videoEditor_getPixels(
- JNIEnv* env,
- jobject thiz,
- jstring path,
- jintArray pixelArray,
- M4OSA_UInt32 width,
- M4OSA_UInt32 height,
- M4OSA_UInt32 timeMS)
-{
-
- M4OSA_ERR err = M4NO_ERROR;
- M4OSA_Context mContext = M4OSA_NULL;
- jint* m_dst32 = M4OSA_NULL;
-
- const char *pString = env->GetStringUTFChars(path, NULL);
- if (pString == M4OSA_NULL) {
- if (env != NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Input string null");
- }
- return M4ERR_ALLOC;
- }
-
- err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE);
- if (err != M4NO_ERROR || mContext == M4OSA_NULL) {
- if (pString != NULL) {
- env->ReleaseStringUTFChars(path, pString);
- }
- if (env != NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed");
- }
- }
-
- m_dst32 = env->GetIntArrayElements(pixelArray, NULL);
-
- err = ThumbnailGetPixels32(mContext, (M4OSA_Int32 *)m_dst32, width,height,&timeMS,0);
- if (err != M4NO_ERROR ) {
- if (env != NULL) {
- jniThrowException(env, "java/lang/RuntimeException",\
- "ThumbnailGetPixels32 failed");
- }
- }
- env->ReleaseIntArrayElements(pixelArray, m_dst32, 0);
-
- ThumbnailClose(mContext);
- if (pString != NULL) {
- env->ReleaseStringUTFChars(path, pString);
- }
-
- return (jint)timeMS;
-}
-
-static jint videoEditor_getPixelsList(
- JNIEnv* env,
- jobject thiz,
- jstring path,
- jintArray pixelArray,
- M4OSA_UInt32 width,
- M4OSA_UInt32 height,
- M4OSA_UInt32 noOfThumbnails,
- jlong startTime,
- jlong endTime,
- jintArray indexArray,
- jobject callback)
-{
-
- M4OSA_ERR err = M4NO_ERROR;
- M4OSA_Context mContext = M4OSA_NULL;
-
- const char *pString = env->GetStringUTFChars(path, NULL);
- if (pString == M4OSA_NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "Input string null");
- return (jint)M4ERR_ALLOC;
- }
-
- err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE);
- if (err != M4NO_ERROR || mContext == M4OSA_NULL) {
- jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed");
- if (pString != NULL) {
- env->ReleaseStringUTFChars(path, pString);
- }
- return (jint)err;
- }
-
- jlong duration = (endTime - startTime);
- M4OSA_UInt32 tolerance = duration / (2 * noOfThumbnails);
- jint* m_dst32 = env->GetIntArrayElements(pixelArray, NULL);
- jint* indices = env->GetIntArrayElements(indexArray, NULL);
- jsize len = env->GetArrayLength(indexArray);
-
- jclass cls = env->GetObjectClass(callback);
- jmethodID mid = env->GetMethodID(cls, "onThumbnail", "(I)V");
-
- for (int i = 0; i < len; i++) {
- int k = indices[i];
- M4OSA_UInt32 timeMS = startTime;
- timeMS += (2 * k + 1) * duration / (2 * noOfThumbnails);
- err = ThumbnailGetPixels32(mContext, ((M4OSA_Int32 *)m_dst32),
- width, height, &timeMS, tolerance);
- if (err != M4NO_ERROR) {
- break;
- }
- env->CallVoidMethod(callback, mid, (jint)k);
- if (env->ExceptionCheck()) {
- err = M4ERR_ALLOC;
- break;
- }
- }
-
- env->ReleaseIntArrayElements(pixelArray, m_dst32, 0);
- env->ReleaseIntArrayElements(indexArray, indices, 0);
-
- ThumbnailClose(mContext);
- if (pString != NULL) {
- env->ReleaseStringUTFChars(path, pString);
- }
-
- if (err != M4NO_ERROR && !env->ExceptionCheck()) {
- jniThrowException(env, "java/lang/RuntimeException",\
- "ThumbnailGetPixels32 failed");
- }
-
- return (jint)err;
-}
-
-static M4OSA_ERR
-videoEditor_toUTF8Fct(
- M4OSA_Void* pBufferIn,
- M4OSA_UInt8* pBufferOut,
- M4OSA_UInt32* bufferOutSize)
-{
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_UInt32 length = 0;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_toUTF8Fct()");
-
- // Determine the length of the input buffer.
- if (M4OSA_NULL != pBufferIn)
- {
- length = strlen((const char *)pBufferIn);
- }
-
- // Check if the output buffer is large enough to hold the input buffer.
- if ((*bufferOutSize) > length)
- {
- // Check if the input buffer is not M4OSA_NULL.
- if (M4OSA_NULL != pBufferIn)
- {
- // Copy the temp path, ignore the result.
- M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length);
- }
- else
- {
- // Set the output buffer to an empty string.
- (*(M4OSA_Char *)pBufferOut) = 0;
- }
- }
- else
- {
- // The buffer is too small.
- result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL;
- }
-
- // Return the buffer output size.
- (*bufferOutSize) = length + 1;
-
- // Return the result.
- return(result);
-}
-
-static M4OSA_ERR
-videoEditor_fromUTF8Fct(
- M4OSA_UInt8* pBufferIn,
- M4OSA_Void* pBufferOut,
- M4OSA_UInt32* bufferOutSize)
-{
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_UInt32 length = 0;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_fromUTF8Fct()");
-
- // Determine the length of the input buffer.
- if (M4OSA_NULL != pBufferIn)
- {
- length = strlen((const char *)pBufferIn);
- }
-
- // Check if the output buffer is large enough to hold the input buffer.
- if ((*bufferOutSize) > length)
- {
- // Check if the input buffer is not M4OSA_NULL.
- if (M4OSA_NULL != pBufferIn)
- {
- // Copy the temp path, ignore the result.
- M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length);
- }
- else
- {
- // Set the output buffer to an empty string.
- (*(M4OSA_Char *)pBufferOut) = 0;
- }
- }
- else
- {
- // The buffer is too small.
- result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL;
- }
-
- // Return the buffer output size.
- (*bufferOutSize) = length + 1;
-
- // Return the result.
- return(result);
-}
-
-static M4OSA_ERR
-videoEditor_getTextRgbBufferFct(
- M4OSA_Void* pRenderingData,
- M4OSA_Void* pTextBuffer,
- M4OSA_UInt32 textBufferSize,
- M4VIFI_ImagePlane** pOutputPlane)
-{
- M4OSA_ERR result = M4NO_ERROR;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getTextRgbBufferFct()");
-
- // Return the result.
- return(result);
-}
-
-static void
-videoEditor_callOnProgressUpdate(
- ManualEditContext* pContext,
- int task,
- int progress)
-{
- JNIEnv* pEnv = NULL;
-
-
- // Attach the current thread.
- pContext->pVM->AttachCurrentThread(&pEnv, NULL);
-
-
- // Call the on completion callback.
- pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId,
- videoEditJava_getEngineCToJava(task), progress);
-
-
- // Detach the current thread.
- pContext->pVM->DetachCurrentThread();
-}
-
-static void
-videoEditor_freeContext(
- JNIEnv* pEnv,
- ManualEditContext** ppContext)
-{
- ManualEditContext* pContext = M4OSA_NULL;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_freeContext");
-
- // Set the context pointer.
- pContext = (*ppContext);
-
- // Check if the context was set.
- if (M4OSA_NULL != pContext)
- {
- // Check if a global reference to the engine object was set.
- if (NULL != pContext->engine)
- {
- // Free the global reference.
- pEnv->DeleteGlobalRef(pContext->engine);
- pContext->engine = NULL;
- }
-
- // Check if the temp path was set.
- if (M4OSA_NULL != pContext->initParams.pTempPath)
- {
- // Free the memory allocated for the temp path.
- videoEditOsal_free(pContext->initParams.pTempPath);
- pContext->initParams.pTempPath = M4OSA_NULL;
- }
-
- // Check if the file writer was set.
- if (M4OSA_NULL != pContext->initParams.pFileWritePtr)
- {
- // Free the memory allocated for the file writer.
- videoEditOsal_free(pContext->initParams.pFileWritePtr);
- pContext->initParams.pFileWritePtr = M4OSA_NULL;
- }
-
- // Check if the file reader was set.
- if (M4OSA_NULL != pContext->initParams.pFileReadPtr)
- {
- // Free the memory allocated for the file reader.
- videoEditOsal_free(pContext->initParams.pFileReadPtr);
- pContext->initParams.pFileReadPtr = M4OSA_NULL;
- }
-
- // Free the memory allocated for the context.
- videoEditOsal_free(pContext);
- pContext = M4OSA_NULL;
-
- // Reset the context pointer.
- (*ppContext) = M4OSA_NULL;
- }
-}
-
-static jobject
-videoEditor_getVersion(
- JNIEnv* pEnv,
- jobject thiz)
-{
- bool isSuccessful = true;
- jobject version = NULL;
- M4_VersionInfo versionInfo = {0, 0, 0, 0};
- M4OSA_ERR result = M4NO_ERROR;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion()");
-
- versionInfo.m_structSize = sizeof(versionInfo);
- versionInfo.m_major = VIDEOEDITOR_VERSION_MAJOR;
- versionInfo.m_minor = VIDEOEDITOR_VERSION_MINOR;
- versionInfo.m_revision = VIDEOEDITOR_VERSION_REVISION;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion() major %d,\
- minor %d, revision %d", versionInfo.m_major, versionInfo.m_minor, versionInfo.m_revision);
-
- // Create a version object.
- videoEditClasses_createVersion(&isSuccessful, pEnv, &versionInfo, &version);
-
- // Return the version object.
- return(version);
-}
-
-static void
-videoEditor_init(
- JNIEnv* pEnv,
- jobject thiz,
- jstring tempPath,
- jstring libraryPath)
-{
- bool initialized = true;
- ManualEditContext* pContext = M4OSA_NULL;
- VideoEditJava_EngineMethodIds methodIds = {NULL};
- M4OSA_Char* pLibraryPath = M4OSA_NULL;
- M4OSA_Char* pTextRendererPath = M4OSA_NULL;
- M4OSA_UInt32 textRendererPathLength = 0;
- M4OSA_ERR result = M4NO_ERROR;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_init()");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&initialized, pEnv, thiz);
-
- // Get the engine method ids.
- videoEditJava_getEngineMethodIds(&initialized, pEnv, &methodIds);
-
- // Validate the tempPath parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&initialized, pEnv,
- (NULL == tempPath),
- "tempPath is null");
-
- // Make sure that the context was not set already.
- videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
- (M4OSA_NULL != pContext),
- "already initialized");
-
- // Check if the initialization succeeded (required because of dereferencing of psContext,
- // and freeing when initialization fails).
- if (initialized)
- {
- // Allocate a new context.
- pContext = new ManualEditContext;
-
- // Check if the initialization succeeded (required because of dereferencing of psContext).
- //if (initialized)
- if (pContext != NULL)
- {
- // Set the state to not initialized.
- pContext->state = ManualEditState_NOT_INITIALIZED;
-
- // Allocate a file read pointer structure.
- pContext->initParams.pFileReadPtr =
- (M4OSA_FileReadPointer*)videoEditOsal_alloc(&initialized, pEnv,
- sizeof(M4OSA_FileReadPointer), "FileReadPointer");
-
- // Allocate a file write pointer structure.
- pContext->initParams.pFileWritePtr =
- (M4OSA_FileWriterPointer*)videoEditOsal_alloc(&initialized, pEnv,
- sizeof(M4OSA_FileWriterPointer), "FileWriterPointer");
-
- // Get the temp path.
- M4OSA_Char* tmpString =
- (M4OSA_Char *)videoEditJava_getString(&initialized, pEnv, tempPath,
- NULL, M4OSA_NULL);
- M4OSA_UInt32 length = strlen((const char *)tmpString);
- // Malloc additional 2 bytes for beginning and tail separator.
- M4OSA_UInt32 pathLength = length + 2;
-
- pContext->initParams.pTempPath = (M4OSA_Char *)
- M4OSA_32bitAlignedMalloc(pathLength, 0x0, (M4OSA_Char *)"tempPath");
-
- //initialize the first char. so that strcat works.
- M4OSA_Char *ptmpChar = (M4OSA_Char*)pContext->initParams.pTempPath;
- ptmpChar[0] = 0x00;
- strncat((char *)pContext->initParams.pTempPath, (const char *)tmpString,
- length);
- strncat((char *)pContext->initParams.pTempPath, (const char *)"/", (size_t)1);
- free(tmpString);
- tmpString = NULL;
- pContext->mIsUpdateOverlay = false;
- pContext->mOverlayFileName = NULL;
- pContext->decoders = NULL;
- }
-
- // Check if the initialization succeeded
- // (required because of dereferencing of pContext, pFileReadPtr and pFileWritePtr).
- if (initialized)
- {
-
- // Initialize the OSAL file system function pointers.
- videoEditOsal_getFilePointers(pContext->initParams.pFileReadPtr ,
- pContext->initParams.pFileWritePtr);
-
- // Set the UTF8 conversion functions.
- pContext->initParams.pConvToUTF8Fct = videoEditor_toUTF8Fct;
- pContext->initParams.pConvFromUTF8Fct = videoEditor_fromUTF8Fct;
-
- // Set the callback method ids.
- pContext->onProgressUpdateMethodId = methodIds.onProgressUpdate;
-
- // Set the virtual machine.
- pEnv->GetJavaVM(&(pContext->pVM));
-
- // Create a global reference to the engine object.
- pContext->engine = pEnv->NewGlobalRef(thiz);
-
- // Check if the global reference could be created.
- videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
- (NULL == pContext->engine), M4NO_ERROR);
- }
-
- // Check if the initialization succeeded (required because of dereferencing of pContext).
- if (initialized)
- {
- // Log the API call.
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4xVSS_Init()");
-
- // Initialize the visual studio library.
- result = M4xVSS_Init(&pContext->engineContext, &pContext->initParams);
-
- // Log the result.
- VIDEOEDIT_LOG_RESULT(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- videoEditOsal_getResultString(result));
-
- // Check if the library could be initialized.
- videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
- (M4NO_ERROR != result), result);
-
- // Get platform video decoder capablities.
- result = M4xVSS_getVideoDecoderCapabilities(&pContext->decoders);
-
- videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
- (M4NO_ERROR != result), result);
- }
-
- if(initialized)
- {
- pContext->mPreviewController = new VideoEditorPreviewController();
- videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
- (M4OSA_NULL == pContext->mPreviewController),
- "not initialized");
- pContext->mAudioSettings =
- (M4xVSS_AudioMixingSettings *)
- M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_AudioMixingSettings),0x0,
- (M4OSA_Char *)"mAudioSettings");
- videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
- (M4OSA_NULL == pContext->mAudioSettings),
- "not initialized");
- pContext->mAudioSettings->pFile = M4OSA_NULL;
- pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
- pContext->mAudioSettings->bRemoveOriginal = 0;
- pContext->mAudioSettings->uiNbChannels = 0;
- pContext->mAudioSettings->uiSamplingFrequency = 0;
- pContext->mAudioSettings->uiExtendedSamplingFrequency = 0;
- pContext->mAudioSettings->uiAddCts = 0;
- pContext->mAudioSettings->uiAddVolume = 0;
- pContext->mAudioSettings->beginCutMs = 0;
- pContext->mAudioSettings->endCutMs = 0;
- pContext->mAudioSettings->fileType = 0;
- pContext->mAudioSettings->bLoop = 0;
- pContext->mAudioSettings->uiInDucking_lowVolume = 0;
- pContext->mAudioSettings->bInDucking_enable = 0;
- pContext->mAudioSettings->uiBTChannelCount = 0;
- pContext->mAudioSettings->uiInDucking_threshold = 0;
- }
- // Check if the library could be initialized.
- if (initialized)
- {
- // Set the state to initialized.
- pContext->state = ManualEditState_INITIALIZED;
- }
-
- // Set the context.
- videoEditClasses_setContext(&initialized, pEnv, thiz, (void* )pContext);
- pLibraryPath = M4OSA_NULL;
-
- pContext->pEditSettings = M4OSA_NULL;
- // Cleanup if anything went wrong during initialization.
- if (!initialized)
- {
- // Free the context.
- videoEditor_freeContext(pEnv, &pContext);
- }
- }
-}
-
-/*+ PROGRESS CB */
-static
-M4OSA_ERR videoEditor_processClip(
- JNIEnv* pEnv,
- jobject thiz,
- int unuseditemID) {
-
- bool loaded = true;
- ManualEditContext* pContext = NULL;
- M4OSA_UInt8 progress = 0;
- M4OSA_UInt8 progressBase = 0;
- M4OSA_UInt8 lastProgress = 0;
- M4OSA_ERR result = M4NO_ERROR;
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // We start in Analyzing state
- pContext->state = ManualEditState_INITIALIZED;
- M4OSA_ERR completionResult = M4VSS3GPP_WAR_ANALYZING_DONE;
- ManualEditState completionState = ManualEditState_OPENED;
- ManualEditState errorState = ManualEditState_ANALYZING_ERROR;
-
- // While analyzing progress goes from 0 to 10 (except Kenburn clip
- // generation, which goes from 0 to 50)
- progressBase = 0;
-
- // Set the text rendering function.
- if (M4OSA_NULL != pContext->pTextRendererFunction)
- {
- // Use the text renderer function in the library.
- pContext->pEditSettings->xVSS.pTextRenderingFct = pContext->pTextRendererFunction;
- }
- else
- {
- // Use the internal text renderer function.
- pContext->pEditSettings->xVSS.pTextRenderingFct = videoEditor_getTextRgbBufferFct;
- }
-
- // Send the command.
- ALOGV("videoEditor_processClip ITEM %d Calling M4xVSS_SendCommand()", unuseditemID);
- result = M4xVSS_SendCommand(pContext->engineContext, pContext->pEditSettings);
- ALOGV("videoEditor_processClip ITEM %d M4xVSS_SendCommand() returned 0x%x",
- unuseditemID, (unsigned int) result);
-
- // Remove warnings indications (we only care about errors here)
- if ((result == M4VSS3GPP_WAR_TRANSCODING_NECESSARY)
- || (result == M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED)) {
- result = M4NO_ERROR;
- }
-
- // Send the first progress indication (=0)
- ALOGV("VERY FIRST PROGRESS videoEditor_processClip ITEM %d Progress indication %d",
- unuseditemID, progress);
- pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId,
- unuseditemID, progress);
-
- // Check if a task is being performed.
- // ??? ADD STOPPING MECHANISM
- ALOGV("videoEditor_processClip Entering processing loop");
- M4OSA_UInt8 prevReportedProgress = 0;
- while((result == M4NO_ERROR)
- &&(pContext->state!=ManualEditState_SAVED)
- &&(pContext->state!=ManualEditState_STOPPING)) {
-
- // Perform the next processing step.
- //ALOGV("LVME_processClip Entering M4xVSS_Step()");
- result = M4xVSS_Step(pContext->engineContext, &progress);
-
- if (progress != prevReportedProgress) {
- prevReportedProgress = progress;
- // Log the 1 % .. 100 % progress after processing.
- if (M4OSA_TRUE ==
- pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
- // For KenBurn clip generation, return 0 to 50
- // for Analysis phase and 50 to 100 for Saving phase
- progress = progressBase + progress/2;
- } else {
- // For export/transition clips, 0 to 10 for Analysis phase
- // and 10 to 100 for Saving phase
- if (ManualEditState_INITIALIZED == pContext->state) {
- progress = 0.1*progress;
- } else {
- progress = progressBase + 0.9*progress;
- }
- }
-
- if (progress > lastProgress)
- {
- // Send a progress notification.
- ALOGV("videoEditor_processClip ITEM %d Progress indication %d",
- unuseditemID, progress);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onProgressUpdateMethodId,
- unuseditemID, progress);
- lastProgress = progress;
- }
- }
-
- // Check if processing has been completed.
- if (result == completionResult)
- {
- // Set the state to the completions state.
- pContext->state = completionState;
- ALOGV("videoEditor_processClip ITEM %d STATE changed to %d",
- unuseditemID, pContext->state);
-
- // Reset progress indication, as we switch to next state
- lastProgress = 0;
-
- // Reset error code, as we start a new round of processing
- result = M4NO_ERROR;
-
- // Check if we are analyzing input
- if (pContext->state == ManualEditState_OPENED) {
- // File is opened, we must start saving it
- ALOGV("videoEditor_processClip Calling M4xVSS_SaveStart()");
- result = M4xVSS_SaveStart(pContext->engineContext,
- (M4OSA_Char*)pContext->pEditSettings->pOutputFile,
- (M4OSA_UInt32)pContext->pEditSettings->uiOutputPathSize);
- ALOGV("videoEditor_processClip ITEM %d SaveStart() returned 0x%x",
- unuseditemID, (unsigned int) result);
-
- // Set the state to saving.
- pContext->state = ManualEditState_SAVING;
- completionState = ManualEditState_SAVED;
- completionResult = M4VSS3GPP_WAR_SAVING_DONE;
- errorState = ManualEditState_SAVING_ERROR;
-
- // While saving, progress goes from 10 to 100
- // except for Kenburn clip which goes from 50 to 100
- if (M4OSA_TRUE ==
- pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
- progressBase = 50;
- } else {
- progressBase = 10;
- }
- }
- // Check if we encoding is ongoing
- else if (pContext->state == ManualEditState_SAVED) {
-
- // Send a progress notification.
- progress = 100;
- ALOGV("videoEditor_processClip ITEM %d Last progress indication %d",
- unuseditemID, progress);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onProgressUpdateMethodId,
- unuseditemID, progress);
-
-
- // Stop the encoding.
- ALOGV("videoEditor_processClip Calling M4xVSS_SaveStop()");
- result = M4xVSS_SaveStop(pContext->engineContext);
- ALOGV("videoEditor_processClip M4xVSS_SaveStop() returned 0x%x", result);
- }
- // Other states are unexpected
- else {
- result = M4ERR_STATE;
- ALOGE("videoEditor_processClip ITEM %d State ERROR 0x%x",
- unuseditemID, (unsigned int) result);
- }
- }
-
- // Check if an error occurred.
- if (result != M4NO_ERROR)
- {
- // Set the state to the error state.
- pContext->state = errorState;
-
- // Log the result.
- ALOGE("videoEditor_processClip ITEM %d Processing ERROR 0x%x",
- unuseditemID, (unsigned int) result);
- }
- }
-
- // Return the error result
- ALOGE("videoEditor_processClip ITEM %d END 0x%x", unuseditemID, (unsigned int) result);
- return result;
-}
-/*+ PROGRESS CB */
-
-static jint
-videoEditor_generateClip(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings) {
- bool loaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
-
- ALOGV("videoEditor_generateClip START");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
- Mutex::Autolock autoLock(pContext->mLock);
-
- // Validate the settings parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&loaded, pEnv,
- (NULL == settings),
- "settings is null");
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Load the clip settings
- ALOGV("videoEditor_generateClip Calling videoEditor_loadSettings");
- videoEditor_loadSettings(pEnv, thiz, settings);
- ALOGV("videoEditor_generateClip videoEditor_loadSettings returned");
-
- // Generate the clip
- ALOGV("videoEditor_generateClip Calling LVME_processClip");
- result = videoEditor_processClip(pEnv, thiz, 0 /*item id is unused*/);
- ALOGV("videoEditor_generateClip videoEditor_processClip returned 0x%x", result);
-
- if (pContext->state != ManualEditState_INITIALIZED) {
- // Free up memory (whatever the result)
- videoEditor_unloadSettings(pEnv, thiz);
- }
-
- ALOGV("videoEditor_generateClip END 0x%x", (unsigned int) result);
- return (jint)result;
-}
-
-static void
-videoEditor_loadSettings(
- JNIEnv* pEnv,
- jobject thiz,
- jobject settings)
-{
- bool needToBeLoaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_loadSettings()");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
- pEnv, thiz);
-
- // Validate the settings parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
- (NULL == settings),
- "settings is null");
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Check if the context is valid (required because the context is dereferenced).
- if (needToBeLoaded)
- {
- // Make sure that we are in a correct state.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
- (pContext->state != ManualEditState_INITIALIZED),
- "settings already loaded");
-
- // Retrieve the edit settings.
- if(pContext->pEditSettings != M4OSA_NULL) {
- videoEditClasses_freeEditSettings(&pContext->pEditSettings);
- pContext->pEditSettings = M4OSA_NULL;
- }
- videoEditClasses_getEditSettings(&needToBeLoaded, pEnv, settings,
- &pContext->pEditSettings,true);
- }
-
- // Check if the edit settings could be retrieved.
- if (needToBeLoaded)
- {
- // Log the edit settings.
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "inside load settings");
- VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings);
- }
- ALOGV("videoEditor_loadSettings END");
-}
-
-
-
-static void
-videoEditor_unloadSettings(
- JNIEnv* pEnv,
- jobject thiz)
-{
- bool needToBeUnLoaded = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_unloadSettings()");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeUnLoaded, pEnv, thiz);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- // Check if the context is valid (required because the context is dereferenced).
- if (needToBeUnLoaded)
- {
- ALOGV("videoEditor_unloadSettings state %d", pContext->state);
- // Make sure that we are in a correct state.
- videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv,
- ((pContext->state != ManualEditState_ANALYZING ) &&
- (pContext->state != ManualEditState_ANALYZING_ERROR) &&
- (pContext->state != ManualEditState_OPENED ) &&
- (pContext->state != ManualEditState_SAVING_ERROR ) &&
- (pContext->state != ManualEditState_SAVED ) &&
- (pContext->state != ManualEditState_STOPPING ) ),
- "videoEditor_unloadSettings no load settings in progress");
- }
-
- // Check if we are in a correct state.
- if (needToBeUnLoaded)
- {
- // Check if the thread could be stopped.
- if (needToBeUnLoaded)
- {
- // Close the command.
- ALOGV("videoEditor_unloadSettings Calling M4xVSS_CloseCommand()");
- result = M4xVSS_CloseCommand(pContext->engineContext);
- ALOGV("videoEditor_unloadSettings M4xVSS_CloseCommand() returned 0x%x",
- (unsigned int)result);
-
- // Check if the command could be closed.
- videoEditJava_checkAndThrowRuntimeException(&needToBeUnLoaded, pEnv,
- (M4NO_ERROR != result), result);
- }
-
- // Check if the command could be closed.
- if (needToBeUnLoaded)
- {
- // Free the edit settings.
- //videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-
- // Reset the thread result.
- pContext->threadResult = M4NO_ERROR;
-
- // Reset the thread progress.
- pContext->threadProgress = 0;
-
- // Set the state to initialized.
- pContext->state = ManualEditState_INITIALIZED;
- }
- }
-}
-
-static void
-videoEditor_stopEncoding(
- JNIEnv* pEnv,
- jobject thiz)
-{
- bool stopped = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
-
- ALOGV("videoEditor_stopEncoding START");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&stopped, pEnv, thiz);
-
- // Change state and get Lock
- // This will ensure the generateClip function exits
- pContext->state = ManualEditState_STOPPING;
- Mutex::Autolock autoLock(pContext->mLock);
-
- // Make sure that the context was set.
- videoEditJava_checkAndThrowIllegalStateException(&stopped, pEnv,
- (M4OSA_NULL == pContext),
- "not initialized");
-
- if (stopped) {
-
- // Check if the command should be closed.
- if (pContext->state != ManualEditState_INITIALIZED)
- {
- // Close the command.
- ALOGV("videoEditor_stopEncoding Calling M4xVSS_CloseCommand()");
- result = M4xVSS_CloseCommand(pContext->engineContext);
- ALOGV("videoEditor_stopEncoding M4xVSS_CloseCommand() returned 0x%x",
- (unsigned int)result);
- }
-
- // Check if the command could be closed.
- videoEditJava_checkAndThrowRuntimeException(&stopped, pEnv,
- (M4NO_ERROR != result), result);
-
- // Free the edit settings.
- videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-
- // Set the state to initialized.
- pContext->state = ManualEditState_INITIALIZED;
- }
-
-}
-
-static void
-videoEditor_release(
- JNIEnv* pEnv,
- jobject thiz)
-{
- bool released = true;
- ManualEditContext* pContext = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_release()");
-
- // Get the context.
- pContext = (ManualEditContext*)videoEditClasses_getContext(&released, pEnv, thiz);
-
- // If context is not set, return (we consider release already happened)
- if (pContext == NULL) {
- ALOGV("videoEditor_release Nothing to do, context is aleady NULL");
- return;
- }
-
-
- // Check if the context is valid (required because the context is dereferenced).
- if (released)
- {
- if (pContext->state != ManualEditState_INITIALIZED)
- {
- // Change state and get Lock
- // This will ensure the generateClip function exits if it is running
- pContext->state = ManualEditState_STOPPING;
- Mutex::Autolock autoLock(pContext->mLock);
- }
-
- // Reset the context.
- videoEditClasses_setContext(&released, pEnv, thiz, (void *)M4OSA_NULL);
-
- // Check if the command should be closed.
- if (pContext->state != ManualEditState_INITIALIZED)
- {
- // Close the command.
- ALOGV("videoEditor_release Calling M4xVSS_CloseCommand() state =%d",
- pContext->state);
- result = M4xVSS_CloseCommand(pContext->engineContext);
- ALOGV("videoEditor_release M4xVSS_CloseCommand() returned 0x%x",
- (unsigned int)result);
-
- // Check if the command could be closed.
- videoEditJava_checkAndThrowRuntimeException(&released, pEnv,
- (M4NO_ERROR != result), result);
- }
-
- // Cleanup the engine.
- ALOGV("videoEditor_release Calling M4xVSS_CleanUp()");
- result = M4xVSS_CleanUp(pContext->engineContext);
- ALOGV("videoEditor_release M4xVSS_CleanUp() returned 0x%x", (unsigned int)result);
-
- // Check if the cleanup succeeded.
- videoEditJava_checkAndThrowRuntimeException(&released, pEnv,
- (M4NO_ERROR != result), result);
-
- // Free the edit settings.
- videoEditClasses_freeEditSettings(&pContext->pEditSettings);
- pContext->pEditSettings = M4OSA_NULL;
-
-
- if(pContext->mPreviewController != M4OSA_NULL)
- {
- delete pContext->mPreviewController;
- pContext->mPreviewController = M4OSA_NULL;
- }
-
- // Free the mAudioSettings context.
- if(pContext->mAudioSettings != M4OSA_NULL)
- {
- if (pContext->mAudioSettings->pFile != NULL) {
- free(pContext->mAudioSettings->pFile);
- pContext->mAudioSettings->pFile = M4OSA_NULL;
- }
- if (pContext->mAudioSettings->pPCMFilePath != NULL) {
- free(pContext->mAudioSettings->pPCMFilePath);
- pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
- }
-
- free(pContext->mAudioSettings);
- pContext->mAudioSettings = M4OSA_NULL;
- }
- // Free video Decoders capabilities
- if (pContext->decoders != M4OSA_NULL) {
- VideoDecoder *pDecoder = NULL;
- VideoComponentCapabilities *pComponents = NULL;
- int32_t decoderNumber = pContext->decoders->decoderNumber;
- if (pContext->decoders->decoder != NULL &&
- decoderNumber > 0) {
- pDecoder = pContext->decoders->decoder;
- for (int32_t k = 0; k < decoderNumber; k++) {
- // free each component
- ALOGV("decoder index :%d",k);
- if (pDecoder != NULL &&
- pDecoder->component != NULL &&
- pDecoder->componentNumber > 0) {
- ALOGV("component number %d",pDecoder->componentNumber);
- int32_t componentNumber =
- pDecoder->componentNumber;
-
- pComponents = pDecoder->component;
- for (int32_t i = 0; i< componentNumber; i++) {
- ALOGV("component index :%d",i);
- if (pComponents != NULL &&
- pComponents->profileLevel != NULL) {
- free(pComponents->profileLevel);
- pComponents->profileLevel = NULL;
- }
- pComponents++;
- }
- free(pDecoder->component);
- pDecoder->component = NULL;
- }
-
- pDecoder++;
- }
- free(pContext->decoders->decoder);
- pContext->decoders->decoder = NULL;
- }
- free(pContext->decoders);
- pContext->decoders = NULL;
- }
-
- videoEditor_freeContext(pEnv, &pContext);
- }
-}
-
-static int
-videoEditor_registerManualEditMethods(
- JNIEnv* pEnv)
-{
- int result = -1;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_registerManualEditMethods()");
-
- // Look up the engine class
- jclass engineClazz = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
-
- // Clear any resulting exceptions.
- pEnv->ExceptionClear();
-
- // Check if the engine class was found.
- if (NULL != engineClazz)
- {
- // Register all the methods.
- if (pEnv->RegisterNatives(engineClazz, gManualEditMethods,
- sizeof(gManualEditMethods) / sizeof(gManualEditMethods[0])) == JNI_OK)
- {
- // Success.
- result = 0;
- }
- }
-
- // Return the result.
- return(result);
-}
-
-/*******Audio Graph*******/
-
-static M4OSA_UInt32 getDecibelSound(M4OSA_UInt32 value)
-{
- int dbSound = 1;
-
- if (value == 0) return 0;
-
- if (value > 0x4000 && value <= 0x8000) // 32768
- dbSound = 90;
- else if (value > 0x2000 && value <= 0x4000) // 16384
- dbSound = 84;
- else if (value > 0x1000 && value <= 0x2000) // 8192
- dbSound = 78;
- else if (value > 0x0800 && value <= 0x1000) // 4028
- dbSound = 72;
- else if (value > 0x0400 && value <= 0x0800) // 2048
- dbSound = 66;
- else if (value > 0x0200 && value <= 0x0400) // 1024
- dbSound = 60;
- else if (value > 0x0100 && value <= 0x0200) // 512
- dbSound = 54;
- else if (value > 0x0080 && value <= 0x0100) // 256
- dbSound = 48;
- else if (value > 0x0040 && value <= 0x0080) // 128
- dbSound = 42;
- else if (value > 0x0020 && value <= 0x0040) // 64
- dbSound = 36;
- else if (value > 0x0010 && value <= 0x0020) // 32
- dbSound = 30;
- else if (value > 0x0008 && value <= 0x0010) //16
- dbSound = 24;
- else if (value > 0x0007 && value <= 0x0008) //8
- dbSound = 24;
- else if (value > 0x0003 && value <= 0x0007) // 4
- dbSound = 18;
- else if (value > 0x0001 && value <= 0x0003) //2
- dbSound = 12;
- else if (value > 0x000 && value == 0x0001) // 1
- dbSound = 6;
- else
- dbSound = 0;
-
- return dbSound;
-}
-
-typedef struct
-{
- M4OSA_UInt8 *m_dataAddress;
- M4OSA_UInt32 m_bufferSize;
-} M4AM_Buffer;
-
-
-M4OSA_UInt8 logLookUp[256] = {
-0,120,137,146,154,159,163,167,171,173,176,178,181,182,184,186,188,189,190,192,193,
-194,195,196,198,199,199,200,201,202,203,204,205,205,206,207,207,208,209,209,210,
-211,211,212,212,213,213,214,215,215,216,216,216,217,217,218,218,219,219,220,220,
-220,221,221,222,222,222,223,223,223,224,224,224,225,225,225,226,226,226,227,227,
-227,228,228,228,229,229,229,229,230,230,230,230,231,231,231,232,232,232,232,233,
-233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,236,237,237,237,
-237,237,238,238,238,238,238,239,239,239,239,239,240,240,240,240,240,240,241,241,
-241,241,241,241,242,242,242,242,242,242,243,243,243,243,243,243,244,244,244,244,
-244,244,245,245,245,245,245,245,245,246,246,246,246,246,246,246,247,247,247,247,
-247,247,247,247,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,250,
-250,250,250,250,250,250,250,250,251,251,251,251,251,251,251,251,252,252,252,252,
-252,252,252,252,252,253,253,253,253,253,253,253,253,253,253,254,254,254,254,254,
-254,254,254,254,255,255,255,255,255,255,255,255,255,255,255};
-
-M4OSA_ERR M4MA_generateAudioGraphFile(JNIEnv* pEnv, M4OSA_Char* pInputFileURL,
- M4OSA_Char* pOutFileURL,
- M4OSA_UInt32 samplesPerValue,
- M4OSA_UInt32 channels,
- M4OSA_UInt32 frameDuration,
- ManualEditContext* pContext)
-{
- M4OSA_ERR err;
- M4OSA_Context outFileHandle = M4OSA_NULL;
- M4OSA_Context inputFileHandle = M4OSA_NULL;
- M4AM_Buffer bufferIn = {0, 0};
- M4OSA_UInt32 peakVolumeDbValue = 0;
- M4OSA_UInt32 samplesCountInBytes= 0 , numBytesToRead = 0, index = 0;
- M4OSA_UInt32 writeCount = 0, samplesCountBigEndian = 0, volumeValuesCount = 0;
- M4OSA_Int32 seekPos = 0;
- M4OSA_UInt32 fileSize = 0;
- M4OSA_UInt32 totalBytesRead = 0;
- M4OSA_UInt32 prevProgress = 0;
- bool threadStarted = true;
-
- int dbValue = 0;
- M4OSA_Int16 *ptr16 ;
-
- jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
- videoEditJava_checkAndThrowIllegalStateException(&threadStarted, pEnv,
- (M4OSA_NULL == engineClass),
- "not initialized");
-
- /* register the call back function pointer */
- pContext->onAudioGraphProgressUpdateMethodId =
- pEnv->GetMethodID(engineClass, "onAudioGraphExtractProgressUpdate", "(IZ)V");
-
-
- /* ENTER */
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "ENTER - M4MA_generateAudioGraphFile");
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "Audio Graph samplesPerValue %d channels %d", samplesPerValue, channels);
-
- /******************************************************************************
- OPEN INPUT AND OUTPUT FILES
- *******************************************************************************/
- err = M4OSA_fileReadOpen (&inputFileHandle, pInputFileURL, M4OSA_kFileRead);
- if (inputFileHandle == M4OSA_NULL) {
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "M4MA_generateAudioGraphFile: Cannot open input file 0x%" PRIx32, err);
- return err;
- }
-
- /* get the file size for progress */
- err = M4OSA_fileReadGetOption(inputFileHandle, M4OSA_kFileReadGetFileSize,
- (M4OSA_Void**)&fileSize);
- if ( err != M4NO_ERROR) {
- //LVMEL_LOG_ERROR("M4MA_generateAudioGraphFile : File write failed \n");
- jniThrowException(pEnv, "java/lang/IOException", "file size get option failed");
- //return -1;
- }
-
- err = M4OSA_fileWriteOpen (&outFileHandle,(M4OSA_Char*) pOutFileURL,
- M4OSA_kFileCreate | M4OSA_kFileWrite);
- if (outFileHandle == M4OSA_NULL) {
- if (inputFileHandle != NULL)
- {
- M4OSA_fileReadClose(inputFileHandle);
- }
- return err;
- }
-
- /******************************************************************************
- PROCESS THE SAMPLES
- *******************************************************************************/
- samplesCountInBytes = (samplesPerValue * sizeof(M4OSA_UInt16) * channels);
-
- bufferIn.m_dataAddress = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(samplesCountInBytes*sizeof(M4OSA_UInt16), 0,
- (M4OSA_Char*)"AudioGraph" );
- if ( bufferIn.m_dataAddress != M4OSA_NULL) {
- bufferIn.m_bufferSize = samplesCountInBytes*sizeof(M4OSA_UInt16);
- } else {
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "M4MA_generateAudioGraphFile: Malloc failed for bufferIn.m_dataAddress 0x%" PRIx32,
- M4ERR_ALLOC);
- return M4ERR_ALLOC;
- }
- /* sample to be converted to BIG endian ; store the frame duration */
- samplesCountBigEndian = ((frameDuration>>24)&0xff) | // move byte 3 to byte 0
- ((frameDuration<<8)&0xff0000) | // move byte 1 to byte 2
- ((frameDuration>>8)&0xff00) | // move byte 2 to byte 1
- ((frameDuration<<24)&0xff000000); // byte 0 to byte 3
-
- /* write the samples per value supplied to out file */
- err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian,
- sizeof(M4OSA_UInt32) );
- if (err != M4NO_ERROR) {
- jniThrowException(pEnv, "java/lang/IOException", "file write failed");
- }
-
-
- /* write UIn32 value 0 for no of values as place holder */
- samplesCountBigEndian = 0; /* reusing local var */
- err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian,
- sizeof(M4OSA_UInt32) );
- if (err != M4NO_ERROR) {
- jniThrowException(pEnv, "java/lang/IOException", "file write failed");
- }
-
- /* loop until EOF */
- do
- {
- memset((void *)bufferIn.m_dataAddress,0,bufferIn.m_bufferSize);
-
- numBytesToRead = samplesCountInBytes;
-
- err = M4OSA_fileReadData( inputFileHandle,
- (M4OSA_MemAddr8)bufferIn.m_dataAddress,
- &numBytesToRead );
-
- if (err != M4NO_ERROR) {
- // if out value of bytes-read is 0, break
- if ( numBytesToRead == 0) {
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "numBytesToRead 0x%" PRIx32,
- numBytesToRead);
- break; /* stop if file is empty or EOF */
- }
- }
-
- ptr16 = (M4OSA_Int16*)bufferIn.m_dataAddress;
-
- peakVolumeDbValue = 0;
- index = 0;
-
- // loop through half the lenght frame bytes read 'cause its 16 bits samples
- while (index < (numBytesToRead / 2)) {
- /* absolute values of 16 bit sample */
- if (ptr16[index] < 0) {
- ptr16[index] = -(ptr16[index]);
- }
- peakVolumeDbValue = (peakVolumeDbValue > (M4OSA_UInt32)ptr16[index] ?\
- peakVolumeDbValue : (M4OSA_UInt32)ptr16[index]);
- index++;
- }
-
- // move 7 bits , ignore sign bit
- dbValue = (peakVolumeDbValue >> 7);
- dbValue = logLookUp[(M4OSA_UInt8)dbValue];
-
- err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&dbValue, sizeof(M4OSA_UInt8) );
- if (err != M4NO_ERROR) {
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "M4MA_generateAudioGraphFile : File write failed");
- break;
- }
-
- volumeValuesCount ++;
- totalBytesRead += numBytesToRead;
-
- if ((((totalBytesRead*100)/fileSize)) != prevProgress) {
- if ( (pContext->threadProgress != prevProgress) && (prevProgress != 0 )) {
- //pContext->threadProgress = prevProgress;
- //onWveformProgressUpdateMethodId(prevProgress, 0);
- //LVME_callAudioGraphOnProgressUpdate(pContext, 0, prevProgress);
- pEnv->CallVoidMethod(pContext->engine,
- pContext->onAudioGraphProgressUpdateMethodId,
- prevProgress, 0);
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pContext->threadProgress %d",
- prevProgress);
- }
- }
- prevProgress = (((totalBytesRead*100)/fileSize));
-
- } while (numBytesToRead != 0);
-
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "loop 0x%" PRIx32, volumeValuesCount);
-
- /* if some error occured in fwrite */
- if (numBytesToRead != 0) {
- //err = -1;
- jniThrowException(pEnv, "java/lang/IOException", "numBytesToRead != 0 ; file write failed");
- }
-
- /* write the count in place holder after seek */
- seekPos = sizeof(M4OSA_UInt32);
- err = M4OSA_fileWriteSeek(outFileHandle, M4OSA_kFileSeekBeginning,
- &seekPos /* after samples per value */);
- if ( err != M4NO_ERROR) {
- jniThrowException(pEnv, "java/lang/IOException", "file seek failed");
- } else {
- volumeValuesCount = ((volumeValuesCount>>24)&0xff) | // move byte 3 to byte 0
- ((volumeValuesCount<<8)&0xff0000) | // move byte 1 to byte 2
- ((volumeValuesCount>>8)&0xff00) | // move byte 2 to byte 1
- ((volumeValuesCount<<24)&0xff000000); // byte 0 to byte 3
-
- err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&volumeValuesCount,
- sizeof(M4OSA_UInt32) );
- if ( err != M4NO_ERROR) {
- jniThrowException(pEnv, "java/lang/IOException", "file write failed");
- }
- }
-
- /******************************************************************************
- CLOSE AND FREE ALLOCATIONS
- *******************************************************************************/
- free(bufferIn.m_dataAddress);
- M4OSA_fileReadClose(inputFileHandle);
- M4OSA_fileWriteClose(outFileHandle);
- /* final finish callback */
- pEnv->CallVoidMethod(pContext->engine, pContext->onAudioGraphProgressUpdateMethodId, 100, 0);
-
- /* EXIT */
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "EXIT - M4MA_generateAudioGraphFile");
-
- return err;
-}
-
-static jint videoEditor_generateAudioWaveFormSync (JNIEnv* pEnv, jobject thiz,
- jstring pcmfilePath,
- jstring outGraphfilePath,
- jint frameDuration, jint channels,
- jint samplesCount)
-{
- M4OSA_ERR result = M4NO_ERROR;
- ManualEditContext* pContext = M4OSA_NULL;
- bool needToBeLoaded = true;
- const char *pPCMFilePath, *pStringOutAudioGraphFile;
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_generateAudioWaveFormSync() ");
-
- /* Get the context. */
- pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
- if (pContext == M4OSA_NULL) {
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_generateAudioWaveFormSync() - pContext is NULL ");
- }
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_generateAudioWaveFormSync Retrieving pStringOutAudioGraphFile");
-
- pPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL);
- if (pPCMFilePath == M4OSA_NULL) {
- jniThrowException(pEnv, "java/lang/RuntimeException",
- "Input string PCMFilePath is null");
- result = M4ERR_PARAMETER;
- goto out;
- }
-
- pStringOutAudioGraphFile = pEnv->GetStringUTFChars(outGraphfilePath, NULL);
- if (pStringOutAudioGraphFile == M4OSA_NULL) {
- jniThrowException(pEnv, "java/lang/RuntimeException",
- "Input string outGraphfilePath is null");
- result = M4ERR_PARAMETER;
- goto out2;
- }
-
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_generateAudioWaveFormSync Generate the waveform data %s %d %d %d",
- pStringOutAudioGraphFile, frameDuration, channels, samplesCount);
-
- /* Generate the waveform */
- result = M4MA_generateAudioGraphFile(pEnv, (M4OSA_Char*) pPCMFilePath,
- (M4OSA_Char*) pStringOutAudioGraphFile,
- (M4OSA_UInt32) samplesCount,
- (M4OSA_UInt32) channels,
- (M4OSA_UInt32)frameDuration,
- pContext);
-
- pEnv->ReleaseStringUTFChars(outGraphfilePath, pStringOutAudioGraphFile);
-
-out2:
- if (pPCMFilePath != NULL) {
- pEnv->ReleaseStringUTFChars(pcmfilePath, pPCMFilePath);
- }
-
-out:
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
- "videoEditor_generateAudioWaveFormSync pContext->bSkipState ");
-
- return (jint)result;
-}
-
-/******** End Audio Graph *******/
-jint JNI_OnLoad(
- JavaVM* pVm,
- void* pReserved)
-{
- void* pEnv = NULL;
- bool needToBeInitialized = true;
- jint result = -1;
-
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "JNI_OnLoad()");
-
- // Check the JNI version.
- if (pVm->GetEnv(&pEnv, JNI_VERSION_1_4) == JNI_OK)
- {
- // Register the manual edit JNI methods.
- if (videoEditor_registerManualEditMethods((JNIEnv*)pEnv) == 0)
- {
- // Initialize the classes.
- videoEditClasses_init(&needToBeInitialized, (JNIEnv*)pEnv);
- if (needToBeInitialized)
- {
- // Success, return valid version number.
- result = JNI_VERSION_1_4;
- }
- }
- }
-
- // Return the result.
- return(result);
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
deleted file mode 100644
index c12b1f5..0000000
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorOsal"
-
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4VSS3GPP_API.h>
-#include <M4DECODER_Common.h>
-};
-
-
-#define VIDEOEDIT_OSAL_RESULT_STRING_MAX (32)
-
-#define VIDEOEDIT_OSAL_RESULT_INIT(m_result) { m_result, #m_result }
-
-
-typedef struct
-{
- M4OSA_ERR result;
- const char* pName;
-} VideoEdit_Osal_Result;
-
-static const VideoEdit_Osal_Result gkRESULTS[] =
-{
- // M4OSA_Clock.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TIMESCALE_TOO_BIG ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_CLOCK_BAD_REF_YEAR ),
-
- // M4OSA_Error.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4NO_ERROR ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_PARAMETER ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_STATE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_ALLOC ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_CONTEXT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_CONTEXT_FAILED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_STREAM_ID ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_OPTION_ID ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_WRITE_ONLY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READ_ONLY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_NOT_IMPLEMENTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_UNSUPPORTED_MEDIA_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_DATA_YET ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_MORE_STREAM ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_INVALID_TIME ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_MORE_AU ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TIME_OUT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_BUFFER_FULL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_REDIRECT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TOO_MUCH_STREAMS ),
-
- // M4OSA_FileCommon.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_NOT_FOUND ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_LOCKED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_BAD_MODE_ACCESS ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_INVALID_POSITION ),
-
- // M4OSA_Thread.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_THREAD_NOT_STARTED ),
-
- // M4xVSS_API.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_ANALYZING_DONE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_PREVIEW_READY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_SAVING_DONE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_TRANSCODING_NECESSARY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_JPG_TOO_BIG ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4xVSSWAR_BUFFER_OUT_TOO_SMALL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4xVSSERR_NO_MORE_SPACE ),
-
- // M4VSS3GPP_ErrorCodes.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_FILE_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_EFFECT_KIND ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS ),
-#ifdef M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL ),
-#endif
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_3GPP_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU ),
-#ifdef M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU ),
-#endif
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION ),
-#ifdef M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM ),
-#endif
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_STREAM_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP ),
-#ifdef M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC ),
-#endif
-#ifdef M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC ),
-#endif
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INTERNAL_STATE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_LUMA_FILTER_ERROR ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_OUTPUT_FILE_TYPE_ERROR ),
-
- // M4MCS_ErrorCodes.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_WAR_TRANSCODING_DONE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_WAR_MEDIATYPE_NOT_SUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_INPUT_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263 ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263 ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_DURATION_IS_NULL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_H263_FORBIDDEN_IN_MP4_FILE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_H263_PROFILE_NOT_SUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIO_CONVERSION_FAILED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_MAXFILESIZE_TOO_SMALL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_VIDEOBITRATE_TOO_LOW ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_LOW ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_VIDEOBITRATE_TOO_HIGH ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_HIGH ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_NOMORE_SPACE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_FILE_DRM_PROTECTED ),
-
- // M4READER_Common.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READER_UNKNOWN_STREAM_TYPE ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_READER_NO_METADATA ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_READER_INFORMATION_NOT_PRESENT ),
-
- // M4WRITER_Common.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_WRITER_STOP_REQ ),
- // M4DECODER_Common.h
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_VIDEORENDERER_NO_NEW_FRAME ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED ),
- VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_DECODER_H263_NOT_BASELINE )
-};
-
-static const int gkRESULTS_COUNT = (sizeof(gkRESULTS) / sizeof(VideoEdit_Osal_Result));
-
-#ifdef OSAL_MEM_LEAK_DEBUG
-static int gAllocatedBlockCount = 0;
-#endif
-
-const char*
-videoEditOsal_getResultString(
- M4OSA_ERR result)
-{
- static char string[VIDEOEDIT_OSAL_RESULT_STRING_MAX] = "";
- const char* pString = M4OSA_NULL;
- int index = 0;
-
- // Loop over the list with constants.
- for (index = 0;
- ((M4OSA_NULL == pString) && (index < gkRESULTS_COUNT));
- index++)
- {
- // Check if the specified result matches.
- if (result == gkRESULTS[index].result)
- {
- // Set the description.
- pString = gkRESULTS[index].pName;
- }
- }
-
- // Check if no result was found.
- if (M4OSA_NULL == pString)
- {
- // Set the description to a default value.
- M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1,
- (M4OSA_Char*)"<unknown(0x%08X)>", result);
- pString = string;
- }
-
- // Return the result.
- return(pString);
-}
-
-void *
-videoEditOsal_alloc(
- bool* pResult,
- JNIEnv* pEnv,
- size_t size,
- const char* pDescription)
-{
- void *pData = M4OSA_NULL;
-
- // Check if the previous action succeeded.
- if (*pResult)
- {
- // Allocate memory for the settings.
- pData = (M4VSS3GPP_EditSettings*)M4OSA_32bitAlignedMalloc(size, 0, (M4OSA_Char*)pDescription);
- if (M4OSA_NULL != pData)
- {
- // Reset the allocated memory.
- memset((void *)pData, 0,size);
-#ifdef OSAL_MEM_LEAK_DEBUG
- // Update the allocated block count.
- gAllocatedBlockCount++;
-#endif
- }
- else
- {
- // Reset the result flag.
- (*pResult) = false;
-
- // Log the error.
- VIDEOEDIT_LOG_ERROR(ANDROID_LOG_ERROR, "VIDEO_EDITOR_OSAL", "videoEditOsal_alloc,\
- error: unable to allocate memory for %s", pDescription);
-
- // Throw an exception.
- jniThrowException(pEnv, "java/lang/OutOfMemoryError", "unable to allocate memory");
- }
- }
-
- // Return the allocated memory.
- return(pData);
-}
-
-void
-videoEditOsal_free(
- void* pData)
-{
- // Check if memory was allocated.
- if (M4OSA_NULL != pData)
- {
- VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "videoEditOsal_free()");
-
- // Log the API call.
- VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "free");
-
- // Free the memory.
- free(pData);
-#ifdef OSAL_MEM_LEAK_DEBUG
- // Update the allocated block count.
- gAllocatedBlockCount--;
-
- // Log the number of allocated blocks.
- VIDEOEDIT_LOG_ALLOCATION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_OSAL", "allocated, %d blocks",\
- gAllocatedBlockCount);
-#endif
- }
-}
-
-
-void
-videoEditOsal_getFilePointers ( M4OSA_FileReadPointer *pOsaFileReadPtr,
- M4OSA_FileWriterPointer *pOsaFileWritePtr)
-{
- if (pOsaFileReadPtr != M4OSA_NULL)
- {
- // Initialize the filereader function pointers.
- pOsaFileReadPtr->openRead = M4OSA_fileReadOpen;
- pOsaFileReadPtr->readData = M4OSA_fileReadData;
- pOsaFileReadPtr->seek = M4OSA_fileReadSeek;
- pOsaFileReadPtr->closeRead = M4OSA_fileReadClose;
- pOsaFileReadPtr->setOption = M4OSA_fileReadSetOption;
- pOsaFileReadPtr->getOption = M4OSA_fileReadGetOption;
- }
-
- if (pOsaFileWritePtr != M4OSA_NULL)
- {
- // Initialize the filewriter function pointers.
- pOsaFileWritePtr->openWrite = M4OSA_fileWriteOpen;
- pOsaFileWritePtr->writeData = M4OSA_fileWriteData;
- pOsaFileWritePtr->seek = M4OSA_fileWriteSeek;
- pOsaFileWritePtr->Flush = M4OSA_fileWriteFlush;
- pOsaFileWritePtr->closeWrite = M4OSA_fileWriteClose;
- pOsaFileWritePtr->setOption = M4OSA_fileWriteSetOption;
- pOsaFileWritePtr->getOption = M4OSA_fileWriteGetOption;
- }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorOsal.h b/media/jni/mediaeditor/VideoEditorOsal.h
deleted file mode 100644
index 7a6f5ea..0000000
--- a/media/jni/mediaeditor/VideoEditorOsal.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_OSAL_H
-#define VIDEO_EDITOR_OSAL_H
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-extern "C" {
-#include <M4OSA_Error.h>
-#include <M4OSA_Thread.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-};
-
-const char*
-videoEditOsal_getResultString(
- M4OSA_ERR result);
-
-void*
-videoEditOsal_alloc(
- bool* pResult,
- JNIEnv* pEnv,
- size_t size,
- const char* pDescription);
-
-void
-videoEditOsal_free(
- void* pData);
-
-void
-videoEditOsal_startThread(
- bool* pResult,
- JNIEnv* pEnv,
- int stackSize,
- M4OSA_ThreadDoIt callback,
- M4OSA_Context* pContext,
- void* pParam);
-
-void
-videoEditOsal_stopThread(
- bool* pResult,
- JNIEnv* pEnv,
- M4OSA_Context* pContext);
-
-void
-videoEditOsal_getFilePointers ( M4OSA_FileReadPointer *pOsaFileReadPtr,
- M4OSA_FileWriterPointer *pOsaFileWritePtr);
-
-#endif // VIDEO_EDITOR_OSAL_H
-
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
deleted file mode 100644
index ae1a80e..0000000
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ /dev/null
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorPropertiesMain"
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorOsal.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_Error.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4VSS3GPP_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_API.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4DECODER_Common.h>
-#include <M4AD_Common.h>
-};
-
-extern "C" M4OSA_ERR M4MCS_open_normalMode(
- M4MCS_Context pContext,
- M4OSA_Void* pFileIn,
- M4VIDEOEDITING_FileType InputFileType,
- M4OSA_Void* pFileOut,
- M4OSA_Void* pTempFile);
-
-jobject videoEditProp_getProperties(
- JNIEnv* pEnv,
- jobject thiz,
- jstring file);
-
-static void
-getFileAndMediaTypeFromExtension (
- M4OSA_Char* pExtension,
- VideoEditClasses_FileType *pFileType,
- M4VIDEOEDITING_FileType *pClipType);
-
-static M4OSA_ERR
-getClipProperties( JNIEnv* pEnv,
- jobject thiz,
- M4OSA_Char* pFile,
- M4VIDEOEDITING_FileType clipType,
- M4VIDEOEDITING_ClipProperties* pClipProperties);
-
-M4OSA_UInt32
-VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
- M4OSA_Char* pStrIn2,
- M4OSA_Int32* pCmpResult);
-
-jobject videoEditProp_getProperties(
- JNIEnv* pEnv,
- jobject thiz,
- jstring file)
-{
- bool gotten = true;
- M4OSA_Char* pFile = M4OSA_NULL;
- M4OSA_Char* pExtension = M4OSA_NULL;
- M4OSA_UInt32 index = 0;
- M4OSA_Int32 cmpResult = 0;
- VideoEditPropClass_Properties* pProperties = M4OSA_NULL;
- M4VIDEOEDITING_ClipProperties* pClipProperties = M4OSA_NULL;
- M4OSA_ERR result = M4NO_ERROR;
- M4MCS_Context context = M4OSA_NULL;
- M4OSA_FilePosition size = 0;
- M4OSA_UInt32 width = 0;
- M4OSA_UInt32 height = 0;
- jobject properties = NULL;
- M4OSA_Context pOMXContext = M4OSA_NULL;
- M4DECODER_VideoInterface* pOMXVidDecoderInterface = M4OSA_NULL;
- M4AD_Interface* pOMXAudDecoderInterface = M4OSA_NULL;
-
- bool initialized = true;
- VideoEditClasses_FileType fileType = VideoEditClasses_kFileType_Unsupported;
- M4VIDEOEDITING_FileType clipType = M4VIDEOEDITING_kFileType_Unsupported;
-
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
- "videoEditProp_getProperties()");
-
- // Initialize the classes.
- videoEditPropClass_init(&initialized, (JNIEnv*)pEnv);
-
- // Validate the tempPath parameter.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv, (NULL == file), "file is null");
-
- // Get the file path.
- pFile = (M4OSA_Char *)videoEditJava_getString(
- &gotten, pEnv, file, NULL, M4OSA_NULL);
-
- result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
-
- if(M4NO_ERROR != result) {
- // Free the file path.
- videoEditOsal_free(pFile);
- pFile = M4OSA_NULL;
- }
-
- videoEditJava_checkAndThrowIllegalArgumentException(&gotten, pEnv,
- (M4NO_ERROR != result), "file not found");
-
- // Close the file and free the file context
- if (context != NULL) {
- result = M4OSA_fileReadClose(context);
- context = M4OSA_NULL;
- }
-
- // Return if Error
- if (M4NO_ERROR != result) {
- return (properties); // NULL
- }
-
- // Check if the file path is valid.
- if (gotten)
- {
- // Retrieve the extension.
- pExtension = (M4OSA_Char *)strrchr((const char *)pFile, (int)'.');
- if (M4OSA_NULL != pExtension)
- {
- // Skip the dot.
- pExtension++;
-
- // Get the file type and Media type from extension
- getFileAndMediaTypeFromExtension(
- pExtension ,&fileType, &clipType);
- }
- }
-
- // Check if the file type could be determined.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv,
- (VideoEditClasses_kFileType_Unsupported == fileType),
- "file type is not supported");
-
- // Allocate a new properties structure.
- pProperties = (VideoEditPropClass_Properties*)videoEditOsal_alloc(
- &gotten, pEnv,
- sizeof(VideoEditPropClass_Properties), "Properties");
-
- // Check if the context is valid and allocation succeeded
- // (required because of dereferencing of pProperties).
- if (gotten)
- {
- // Check if this type of file needs to be analyzed using MCS.
- if ((VideoEditClasses_kFileType_MP3 == fileType) ||
- (VideoEditClasses_kFileType_MP4 == fileType) ||
- (VideoEditClasses_kFileType_3GPP == fileType) ||
- (VideoEditClasses_kFileType_AMR == fileType) ||
- (VideoEditClasses_kFileType_PCM == fileType) ||
- (VideoEditClasses_kFileType_M4V == fileType))
- {
- // Allocate a new clip properties structure.
- pClipProperties =
- (M4VIDEOEDITING_ClipProperties*)videoEditOsal_alloc(
- &gotten, pEnv,
- sizeof(M4VIDEOEDITING_ClipProperties), "ClipProperties");
-
- // Check if allocation succeeded (required because of
- // dereferencing of pClipProperties).
- if (gotten)
- {
- // Log the API call.
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
- "getClipProperties");
-
- // Get Video clip properties
- result = getClipProperties(
- pEnv, thiz, pFile, clipType, pClipProperties);
-
- if (M4MCS_ERR_FILE_DRM_PROTECTED == result) {
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv,(M4NO_ERROR != result),
- "Invalid File - DRM Protected ");
- } else {
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv,(M4NO_ERROR != result),
- "Invalid File or File not found ");
- }
-
-#ifdef USE_SOFTWARE_DECODER
- /**
- * Input clip with non-multiples of 16 is not supported.
- */
- if ( (pClipProperties->uiVideoWidth %16)
- || (pClipProperties->uiVideoHeight %16) )
- {
- result = M4MCS_ERR_INPUT_VIDEO_SIZE_NON_X16;
- videoEditJava_checkAndThrowIllegalArgumentException(
- &gotten, pEnv, (M4NO_ERROR != result),
- "non x16 input video frame size is not supported");
- }
-#endif /* USE_SOFTWARE_DECODER */
- }
-
- // Check if the properties could be retrieved.
- if (gotten)
- {
- // Set the properties.
- pProperties->uiClipDuration = pClipProperties->uiClipDuration;
- if (M4VIDEOEDITING_kFileType_Unsupported == pClipProperties->FileType)
- {
- pProperties->FileType = VideoEditClasses_kFileType_Unsupported;
- }
- else
- {
- pProperties->FileType = fileType;
- }
- pProperties->VideoStreamType = pClipProperties->VideoStreamType;
- pProperties->uiClipVideoDuration = pClipProperties->uiClipVideoDuration;
- pProperties->uiVideoBitrate = pClipProperties->uiVideoBitrate;
- pProperties->uiVideoWidth = pClipProperties->uiVideoWidth;
- pProperties->uiVideoHeight = pClipProperties->uiVideoHeight;
- pProperties->fAverageFrameRate = pClipProperties->fAverageFrameRate;
- pProperties->uiVideoProfile = pClipProperties->uiVideoProfile;
- pProperties->uiVideoLevel = pClipProperties->uiVideoLevel;
- // Set profile and level support to TRUE, pending check
- pProperties->bProfileSupported = M4OSA_TRUE;
- pProperties->bLevelSupported = M4OSA_TRUE;
- pProperties->AudioStreamType = pClipProperties->AudioStreamType;
- pProperties->uiClipAudioDuration = pClipProperties->uiClipAudioDuration;
- pProperties->uiAudioBitrate = pClipProperties->uiAudioBitrate;
- pProperties->uiNbChannels = pClipProperties->uiNbChannels;
- pProperties->uiSamplingFrequency = pClipProperties->uiSamplingFrequency;
- pProperties->uiRotation = pClipProperties->videoRotationDegrees;
-
- }
-
- // Free the clip properties.
- videoEditOsal_free(pClipProperties);
- pClipProperties = M4OSA_NULL;
- }
- else if ((VideoEditClasses_kFileType_JPG == fileType) ||
- (VideoEditClasses_kFileType_GIF == fileType) ||
- (VideoEditClasses_kFileType_PNG == fileType))
- {
- pProperties->uiClipDuration = 0;
- pProperties->FileType = fileType;
- pProperties->VideoStreamType = M4VIDEOEDITING_kNoneVideo;
- pProperties->uiClipVideoDuration = 0;
- pProperties->uiVideoBitrate = 0;
- pProperties->uiVideoWidth = width;
- pProperties->uiVideoHeight = height;
- pProperties->fAverageFrameRate = 0.0f;
- pProperties->uiVideoProfile = M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
- pProperties->uiVideoLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
- pProperties->AudioStreamType = M4VIDEOEDITING_kNoneAudio;
- pProperties->uiClipAudioDuration = 0;
- pProperties->uiAudioBitrate = 0;
- pProperties->uiNbChannels = 0;
- pProperties->uiSamplingFrequency = 0;
-
- // Added for Handling invalid paths and non existent image files
- // Open the file for reading.
- result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
- if (M4NO_ERROR != result)
- {
- pProperties->FileType = VideoEditClasses_kFileType_Unsupported;
- }
- result = M4OSA_fileReadClose(context);
- context = M4OSA_NULL;
- }
- }
-
- if (M4NO_ERROR == result) {
- // Create a properties object.
- videoEditPropClass_createProperties(&gotten, pEnv, pProperties, &properties);
-
- // Log the properties.
- VIDEOEDIT_PROP_LOG_PROPERTIES(pProperties);
- }
-
- // Free the properties.
- videoEditOsal_free(pProperties);
- pProperties = M4OSA_NULL;
-
- // Free the file path.
- videoEditOsal_free(pFile);
- pFile = M4OSA_NULL;
-
- // Return the Properties object.
- return(properties);
-}
-
-static void getFileAndMediaTypeFromExtension (
- M4OSA_Char *pExtension,
- VideoEditClasses_FileType *pFileType,
- M4VIDEOEDITING_FileType *pClipType)
-{
- M4OSA_Char extension[5] = {0, 0, 0, 0, 0};
- VideoEditClasses_FileType fileType =
- VideoEditClasses_kFileType_Unsupported;
-
- M4VIDEOEDITING_FileType clipType =
- M4VIDEOEDITING_kFileType_Unsupported;
-
- M4OSA_UInt32 index = 0;
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_Int32 cmpResult = 0;
- M4OSA_UInt32 extLength = strlen((const char *)pExtension);
-
- // Assign default
- *pFileType = VideoEditClasses_kFileType_Unsupported;
- *pClipType = M4VIDEOEDITING_kFileType_Unsupported;
-
- // Check if the length of the extension is valid.
- if ((3 == extLength) || (4 == extLength))
- {
- // Convert the extension to lowercase.
- for (index = 0; index < extLength ; index++)
- {
- extension[index] = tolower((int)pExtension[index]);
- }
-
- // Check if the extension is ".mp3".
- if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp3", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_MP3;
- *pClipType = M4VIDEOEDITING_kFileType_MP3;
- }
- // Check if the extension is ".mp4".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp4", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_MP4;
- *pClipType = M4VIDEOEDITING_kFileType_MP4;
- }
- // Check if the extension is ".3gp".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gp", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_3GPP;
- *pClipType = M4VIDEOEDITING_kFileType_3GPP;
- }
- // Check if the extension is ".m4a".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4a", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_3GPP;
- *pClipType = M4VIDEOEDITING_kFileType_3GPP;
- }
- // Check if the extension is ".3gpp".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gpp", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_3GPP;
- *pClipType = M4VIDEOEDITING_kFileType_3GPP;
- }
- // Check if the extension is ".amr".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"amr", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_AMR;
- *pClipType = M4VIDEOEDITING_kFileType_AMR;
- }
- // Check if the extension is ".pcm".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"pcm", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_PCM;
- *pClipType = M4VIDEOEDITING_kFileType_PCM;
- }
- // Check if the extension is ".jpg".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpg", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_JPG;
- }
- // Check if the extension is ".jpeg".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpeg", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_JPG;
- }
- // Check if the extension is ".gif".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"gif", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_GIF;
- }
- // Check if the extension is ".png".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"png", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_PNG;
- }
- // Check if the extension is ".m4v".
- else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4v", &cmpResult)))
- {
- *pFileType = VideoEditClasses_kFileType_M4V;
- *pClipType = M4VIDEOEDITING_kFileType_M4V;
- }
- }
-}
-
-static M4OSA_ERR getClipProperties(
- JNIEnv* pEnv,
- jobject thiz,
- M4OSA_Char* pFile,
- M4VIDEOEDITING_FileType clipType,
- M4VIDEOEDITING_ClipProperties* pClipProperties)
-{
- bool gotten = true;
- M4OSA_ERR result = M4NO_ERROR;
- M4OSA_ERR resultAbort = M4NO_ERROR;
- M4MCS_Context context = M4OSA_NULL;
-
- M4OSA_FileReadPointer fileReadPtr =
- { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
- M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
-
- M4OSA_FileWriterPointer fileWritePtr =
- { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
- M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
-
- // Initialize the OSAL file system function pointers.
- videoEditOsal_getFilePointers(&fileReadPtr , &fileWritePtr);
-
- // Log the API call.
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",\
- "getClipProperties - M4MCS_init()");
-
- // Initialize the MCS context.
- result = M4MCS_init(&context, &fileReadPtr, &fileWritePtr);
-
- // Log the result.
- VIDEOEDIT_PROP_LOG_RESULT(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
- videoEditOsal_getResultString(result));
-
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowRuntimeException(
- &gotten, pEnv, (M4NO_ERROR != result), result);
-
- // Check if opening the MCS context succeeded.
- if (gotten)
- {
- // Log the API call.
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
- "getClipProperties - M4MCS_open_normalMode()");
-
- // Open the MCS in the normal opening mode to
- // retrieve the exact duration
- result = M4MCS_open_normalMode(
- context, pFile, clipType, M4OSA_NULL, M4OSA_NULL);
-
- // Log the result.
- VIDEOEDIT_PROP_LOG_RESULT(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
- videoEditOsal_getResultString(result));
-
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowRuntimeException(
- &gotten, pEnv, (M4NO_ERROR != result), result);
-
- // Check if the MCS could be opened.
- if (gotten)
- {
- // Log the API call.
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
- "getClipProperties - M4MCS_getInputFileProperties()");
-
- // Get the properties.
- result = M4MCS_getInputFileProperties(context, pClipProperties);
-
- // Log the result.
- VIDEOEDIT_PROP_LOG_RESULT(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
- videoEditOsal_getResultString(result));
-
- // Check if the creation succeeded.
- videoEditJava_checkAndThrowRuntimeException(
- &gotten, pEnv, (M4NO_ERROR != result), result);
- }
-
- // Log the API call.
- VIDEOEDIT_LOG_API(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
- "getClipProperties - M4MCS_abort()");
-
- // Close the MCS session.
- resultAbort = M4MCS_abort(context);
-
- if (result == M4NO_ERROR) {
- // Log the result.
- VIDEOEDIT_PROP_LOG_RESULT(
- ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
- videoEditOsal_getResultString(resultAbort));
-
- // Check if the abort succeeded.
- videoEditJava_checkAndThrowRuntimeException(
- &gotten, pEnv, (M4NO_ERROR != resultAbort), resultAbort);
- result = resultAbort;
- }
- }
-
- return result;
-}
-
-M4OSA_UInt32
-VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
- M4OSA_Char* pStrIn2,
- M4OSA_Int32* pCmpResult)
-{
- *pCmpResult = strcmp((const char *)pStrIn1, (const char *)pStrIn2);
- return *pCmpResult;
-}
-
-
diff --git a/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp b/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp
deleted file mode 100644
index 1508246..0000000
--- a/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-
-#include <jni.h>
-#include <JNIHelp.h>
-#include <utils/Log.h>
-#include "VideoBrowserMain.h"
-#include "VideoBrowserInternal.h"
-
-#if (M4OSA_TRACE_LEVEL >= 1)
-#undef M4OSA_TRACE1_0
-#undef M4OSA_TRACE1_1
-#undef M4OSA_TRACE1_2
-#undef M4OSA_TRACE1_3
-
-#define M4OSA_TRACE1_0(a) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a);
-#define M4OSA_TRACE1_1(a,b) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b);
-#define M4OSA_TRACE1_2(a,b,c) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c);
-#define M4OSA_TRACE1_3(a,b,c,d) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c,d);
-#endif
-
-/*
- * Memory format of 'ARGB8888' in skia is RGBA, so ABGR in 32bit little-endian packed format
- * bitmap format is rgb565
- */
-// RED GREEN BLUE ALPHA
-#define RGB565toSKCOLOR(c) ( (((c)&0xF800)>>8) | (((c)&0x7E0)<<5) | (((c)&0x1F)<<19) | 0xFF000000)
-
-#define GetIntField(env, obj, name) env->GetIntField(obj,\
-env->GetFieldID(env->GetObjectClass(obj), name, "I"))
-
-extern "C" M4OSA_ERR NXPSW_FileReaderOptim_init(M4OSA_Void *lowLevel_functionPointers,
- M4OSA_Void *optimized_functionPointers);
-
-/*
- * Video Browser execution context.
- * Based on request for RGB565 or RGB888, m_dst16 or m_dst32
- * will be initialized and used
- */
-typedef struct
-{
- M4OSA_Context m_pVideoBrowser;
- M4OSA_UInt32 m_previousTime;
- M4OSA_Int32* m_dst32;
- M4OSA_Int16* m_dst16;
- unsigned int m_width;
- unsigned int m_height;
- M4OSA_Bool m_bRender;
-} ThumbnailContext;
-
-/**
- ************************************************************************
- * @brief Interface to retrieve the thumbnail pixels
- * @param pContext (IN) Thumbnail Context.
- * @param width (IN) Width of thumbnail
- * @param height (IN) Height of thumbnail
- * @param pTimeMS (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels(const M4OSA_Context pContext,
- M4OSA_Int32* pixelArray,
- M4OSA_UInt32 width, M4OSA_UInt32 height,
- M4OSA_UInt32* pTimeMS, M4OSA_UInt32 tolerance);
-
-
-/**
- ************************************************************************
- * @brief Video browser callback, called when a frame must be displayed
- * @param pInstance (IN) Thumbnail context.
- * @param notificationID (IN) Id of the callback which generated the error
- * @param errCode (IN) Error code from the Core
- * @param pCbData (IN) pointer to data associated wit the callback.
- * @param pCbUserData (IN) pointer to application user data passed in init.
- * @note This callback mechanism is used to request display of an image
- ************************************************************************
-*/
-M4OSA_Void VBcallback( M4OSA_Context pInstance,
- VideoBrowser_Notification notificationID,
- M4OSA_ERR errCode, M4OSA_Void* pCbData,
- M4OSA_Void* pCallbackUserData)
-{
- M4OSA_UInt32 i, j;
- M4OSA_ERR err;
-
- M4OSA_TRACE3_0("inside VBcallback");
- M4VIFI_ImagePlane* pPlane=NULL;
- M4OSA_UInt16* src=NULL;
- ThumbnailContext* pC = NULL;
-
- CHECK_PTR(VBcallback, pCbData, err, M4ERR_PARAMETER);
- CHECK_PTR(VBcallback, pInstance,err, M4ERR_PARAMETER);
-
- pC = (ThumbnailContext*)pCallbackUserData ;
- CHECK_PTR(VBcallback, pC->m_pVideoBrowser, err, M4ERR_PARAMETER);
-
- pPlane = (M4VIFI_ImagePlane*)pCbData;
- src = (M4OSA_UInt16*)pPlane->pac_data;
-
- if (pC->m_dst32 != NULL)
- {
- M4OSA_Int32* dst = pC->m_dst32;
-
- for (j = 0; j < pPlane->u_height; j++)
- {
- for (i = 0; i < pPlane->u_width; i++)
- {
- dst[i] = RGB565toSKCOLOR(src[i]);
- }
- for (i = pPlane->u_width; i < pC->m_width; i++)
- {
- dst[i] = 0;
- }
- src = (M4OSA_UInt16*)((M4OSA_UInt8*)src + pPlane->u_stride);
- dst += pC->m_width;
- }
- }
- else if (pC->m_dst16 != NULL)
- {
- M4OSA_Int16* dst = pC->m_dst16;
-
- for (j = 0; j < pPlane->u_height; j++)
- {
- memcpy((void * )dst, (void * )src, pPlane->u_stride);
- for (i = pPlane->u_width; i < pC->m_width; i++)
- {
- dst[i] = 0;
- }
- src = (M4OSA_UInt16*)((M4OSA_UInt8*)src + pPlane->u_stride);
- dst += pC->m_width;
- }
- }
- else
- {
- CHECK_PTR(VBcallback, NULL, err, M4ERR_PARAMETER);
- }
-
-VBcallback_cleanUp:
-
- return;
-}
-
-M4OSA_ERR ThumbnailOpen(M4OSA_Context *pPContext,
- const M4OSA_Char *pString,
- M4OSA_Bool bRender)
-{
-
- M4OSA_ERR err;
- ThumbnailContext *pContext = M4OSA_NULL;
- VideoBrowser_VideoColorType vbColorType;
-
- CHECK_PTR(ThumbnailOpen, pString, err, M4ERR_BAD_CONTEXT);
-
- /*--- Create context ---*/
- pContext = (ThumbnailContext*)M4OSA_32bitAlignedMalloc(sizeof(ThumbnailContext), VIDEOBROWSER,
- (M4OSA_Char*)"Thumbnail context") ;
- M4OSA_TRACE3_1("context value is = %d",pContext);
- CHECK_PTR(ThumbnailOpen, pContext, err, M4ERR_ALLOC);
-
- memset((void *)pContext, 0,sizeof(ThumbnailContext));
-
- M4OSA_FileReadPointer optFP;
- M4OSA_FileReadPointer llFP;
-
- NXPSW_FileReaderOptim_init(&llFP, &optFP);
- M4OSA_TRACE1_2("ThumbnailOpen: entering videoBrowserCreate with 0x%x %s",
- &pContext->m_pVideoBrowser, pString) ;
-
- pContext->m_bRender = bRender;
- if (bRender == M4OSA_TRUE) {
- //Open is called for rendering the frame.
- //So set YUV420 as the output color format.
- vbColorType = VideoBrowser_kYUV420;
- } else {
- //Open is called for thumbnail Extraction
- //So set BGR565 as the output.
- vbColorType = VideoBrowser_kGB565;
- }
-
- err = videoBrowserCreate(&pContext->m_pVideoBrowser, (M4OSA_Char*)pString,
- VideoBrowser_kVBNormalBliting, &optFP, VBcallback, pContext, vbColorType);
-
- M4OSA_TRACE1_1("err value is = 0x%x",err);
- CHECK_ERR(ThumbnailOpen, err);
- CHECK_PTR(ThumbnailOpen, pContext->m_pVideoBrowser, err, M4ERR_ALLOC);
-
- *pPContext = pContext;
- M4OSA_TRACE1_1("context value is = %d",*pPContext);
-
- return M4NO_ERROR;
-
-ThumbnailOpen_cleanUp:
-
- M4OSA_TRACE1_0("i am inside cleanUP");
- if (M4OSA_NULL != pContext)
- {
- if (M4OSA_NULL != pContext->m_pVideoBrowser)
- {
- videoBrowserCleanUp(pContext->m_pVideoBrowser) ;
- }
- free(pContext) ;
- }
- return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels(const M4OSA_Context pContext,
- M4OSA_Int32* pixelArray,
- M4OSA_UInt32 width, M4OSA_UInt32 height,
- M4OSA_UInt32* pTimeMS, M4OSA_UInt32 tolerance)
-{
- M4OSA_ERR err;
-
- ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
- if ((pC->m_width != width) || (pC->m_height != height))
- {
- err = videoBrowserSetWindow(pC->m_pVideoBrowser, pixelArray,
- 0, 0, width, height);
- CHECK_ERR(ThumbnailGetPixels, err);
- pC->m_width = width;
- pC->m_height = height;
- }
-
- // Alter the pTimeMS to a valid value at which a frame is found
- // m_currentCTS has the actual frame time stamp just ahead of the
- // pTimeMS supplied.
- if ((((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS != 0) &&
- (*pTimeMS >= pC->m_previousTime) &&
- (*pTimeMS < ((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS))
- {
- pC->m_previousTime = *pTimeMS;
- *pTimeMS = ((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS;
- }
- else
- {
- pC->m_previousTime = *pTimeMS;
- }
-
- err = videoBrowserPrepareFrame(pC->m_pVideoBrowser, pTimeMS, tolerance);
- CHECK_ERR(ThumbnailGetPixels, err);
-
- if (pC->m_bRender != M4OSA_TRUE) {
- err = videoBrowserDisplayCurrentFrame(pC->m_pVideoBrowser);
- CHECK_ERR(ThumbnailGetPixels, err);
- }
-
-ThumbnailGetPixels_cleanUp:
-
- return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels32(const M4OSA_Context pContext,
- M4OSA_Int32* pixelArray, M4OSA_UInt32 width,
- M4OSA_UInt32 height, M4OSA_UInt32* timeMS,
- M4OSA_UInt32 tolerance)
-{
-
- M4OSA_ERR err = M4NO_ERROR;
-
- ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
- CHECK_PTR(ThumbnailGetPixels32, pC->m_pVideoBrowser, err, M4ERR_ALLOC) ;
- CHECK_PTR(ThumbnailGetPixels32, pixelArray, err, M4ERR_ALLOC) ;
-
- pC->m_dst16 = NULL;
- pC->m_dst32 = pixelArray;
-
- err = ThumbnailGetPixels(pContext, pixelArray, width, height, timeMS, tolerance);
-
-ThumbnailGetPixels32_cleanUp:
-
- return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels16(const M4OSA_Context pContext,
- M4OSA_Int16* pixelArray, M4OSA_UInt32 width,
- M4OSA_UInt32 height, M4OSA_UInt32* timeMS,
- M4OSA_UInt32 tolerance)
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
- CHECK_PTR(ThumbnailGetPixels16, pC->m_pVideoBrowser, err, M4ERR_ALLOC);
- CHECK_PTR(ThumbnailGetPixels16, pixelArray, err, M4ERR_ALLOC);
-
- pC->m_dst16 = pixelArray;
- pC->m_dst32 = NULL;
-
- err = ThumbnailGetPixels(pContext, (M4OSA_Int32*)pixelArray, width, height,
- timeMS, tolerance);
-
-ThumbnailGetPixels16_cleanUp:
-
- return err;
-}
-
-
-void ThumbnailClose(const M4OSA_Context pContext)
-{
- M4OSA_ERR err;
-
- ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
- CHECK_PTR(ThumbnailClose, pC, err, M4ERR_ALLOC);
-
- if (M4OSA_NULL != pC)
- {
- if (M4OSA_NULL != pC->m_pVideoBrowser)
- {
- videoBrowserCleanUp(pC->m_pVideoBrowser);
- }
- free(pC);
- }
-
-ThumbnailClose_cleanUp:
-
- return;
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorThumbnailMain.h b/media/jni/mediaeditor/VideoEditorThumbnailMain.h
deleted file mode 100644
index 0b3b0c8..0000000
--- a/media/jni/mediaeditor/VideoEditorThumbnailMain.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEOEDITOR_THUMBNAIL_MAIN_H
-#define VIDEOEDITOR_THUMBNAIL_MAIN_H
-
-/**
- ************************************************************************
- * @file VideoEditorThumbnailMain.h
- * @brief Thumbnail extract interface.
- ************************************************************************
-*/
-
-/**
- ************************************************************************
- * @brief Interface to open a Thumbnail session.
- * @param pContext (OUT) Thumbnail Context.
- * @param pString (IN) File path from which thumbnail will be
- * retrieved
- * @param M4OSA_Bool (IN) true if this is for rendering at native layer.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailOpen(M4OSA_Context *pPContext,
- const M4OSA_Char *pString,
- M4OSA_Bool bRender);
-
-/**
- ************************************************************************
- * @brief Interface to retrieve a RGB888 format thumbnail pixels
- * @param pContext (IN) Thumbnail Context.
- * @param pixelArray (OUT) Pointer to array in which pixels data to return
- * @param width (IN) Width of thumbnail
- * @param height (IN) Height of thumbnail
- * @param pTimeMS (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels32(const M4OSA_Context pContext,
- M4OSA_Int32* pixelArray, M4OSA_UInt32 width,
- M4OSA_UInt32 height, M4OSA_UInt32 *timeMS,
- M4OSA_UInt32 tolerance);
-
-/**
- ************************************************************************
- * @brief Interface to retrieve a RGB565 format thumbnail pixels
- * @param pContext (IN) Thumbnail Context.
- * @param pixelArray (OUT) Pointer to array in which pixcel data to return
- * @param width (IN) Width of thumbnail
- * @param height (IN) Height of thumbnail
- * @param pTimeMS (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels16(const M4OSA_Context pContext,
- M4OSA_Int16* pixelArray, M4OSA_UInt32 width,
- M4OSA_UInt32 height, M4OSA_UInt32 *timeMS,
- M4OSA_UInt32 tolerance);
-
-/**
- ************************************************************************
- * @brief Interface to close the Thumbnail session.
- * @param pContext (IN) Thumbnail Context.
- ************************************************************************
-*/
-void ThumbnailClose(const M4OSA_Context pContext);
-
-#endif // VIDEOEDITOR_THUMBNAIL_MAIN_H
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
index 3d5905d..cfc0881 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -17,8 +17,6 @@
package com.android.mediaframeworktest;
import com.android.mediaframeworktest.performance.MediaPlayerPerformance;
-/*Video Editor performance Test cases*/
-import com.android.mediaframeworktest.performance.VideoEditorPerformance;
import junit.framework.TestSuite;
import android.os.Bundle;
@@ -44,8 +42,6 @@
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(MediaPlayerPerformance.class);
- /* Video Editor performance Test cases */
- suite.addTestSuite(VideoEditorPerformance.class);
return suite;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index cbb6642..a9dc886 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -32,11 +32,6 @@
import com.android.mediaframeworktest.functional.audio.MediaPresetReverbTest;
import com.android.mediaframeworktest.functional.audio.MediaVirtualizerTest;
import com.android.mediaframeworktest.functional.audio.MediaVisualizerTest;
-import com.android.mediaframeworktest.functional.videoeditor.MediaItemThumbnailTest;
-import com.android.mediaframeworktest.functional.videoeditor.MediaPropertiesTest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorAPITest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorExportTest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorPreviewTest;
import junit.framework.TestSuite;
import android.os.Bundle;
@@ -76,12 +71,6 @@
suite.addTestSuite(MediaPresetReverbTest.class);
suite.addTestSuite(MediaVirtualizerTest.class);
suite.addTestSuite(MediaVisualizerTest.class);
- /*Test for Video Editor*/
- suite.addTestSuite(MediaItemThumbnailTest.class);
- suite.addTestSuite(MediaPropertiesTest.class);
- suite.addTestSuite(VideoEditorAPITest.class);
- suite.addTestSuite(VideoEditorExportTest.class);
- suite.addTestSuite(VideoEditorPreviewTest.class);
return suite;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
index 0cd784c..5438061 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
@@ -19,8 +19,6 @@
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
import com.android.mediaframeworktest.stress.MediaPlayerStressTest;
-/** Import for Video Editor Stress Test cases*/
-import com.android.mediaframeworktest.stress.VideoEditorStressTest;
import junit.framework.TestSuite;
@@ -30,8 +28,6 @@
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(MediaPlayerStressTest.class);
- /** Video Editor Stress Test cases*/
- suite.addTestSuite(VideoEditorStressTest.class);
return suite;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java
deleted file mode 100644
index dd7c4c6..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Random;
-
-import junit.framework.Assert;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditorFactory;
-import android.util.Log;
-import android.os.Environment;
-
-/**
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- */
-public class VideoEditorHelper extends Assert {
-
- private final String TAG = "VideoEditorMediaNames";
-
- public VideoEditorHelper() {
-
- }
-
- public static final String PROJECT_LOCATION_COMMON =
- Environment.getExternalStorageDirectory().toString() + "/";
-
- public static final String INPUT_FILE_PATH_COMMON = PROJECT_LOCATION_COMMON +
- "media_api/videoeditor/";
-
- // -----------------------------------------------------------------
- // HELPER METHODS
- // -----------------------------------------------------------------
-
- /**
- * This method creates an object of VideoEditor
- *
- * @param projectPath the directory where all files related to project will
- * be stored
- * @param className The class which implements the VideoEditor Class
- * @return the object of VideoEditor
- */
- public VideoEditor createVideoEditor(String projectPath) {
- VideoEditor mVideoEditor = null;
- try {
- mVideoEditor = VideoEditorFactory.create(projectPath);
- assertNotNull("VideoEditor", mVideoEditor);
- } catch (Exception e) {
- fail("Unable to create Video Editor");
- }
- return mVideoEditor;
- }
-
- /**
- *This method deletes the VideoEditor object created using
- * createVideoEditor method
- *
- * @param videoEditor the VideoEditor object which needs to be cleaned up
- */
- public void destroyVideoEditor(VideoEditor videoEditor) {
- // Release VideoEditor
- if (videoEditor != null) {
- try {
- videoEditor.release();
- } catch (Exception e) {
- fail("Unable to destory Video Editor");
- }
- }
- }
-
- /**
- *This Method checks the Range in "RangePercent" (say 10)
- *
- * @param int Expected data
- * @param actual data
- * @return boolean flag which confirms the range matching
- */
- public boolean checkRange(long expected, long actual, long rangePercent) {
- long range = 0;
- range = (100 * actual) / expected;
-
- Log.i("checkRange", "Range = " + range);
- if ((range > (100 - rangePercent)) && (range < (100 + rangePercent))) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- *This Method Creates a Bitmap with the given input file
- *
- * @param file the Input whose Bitmap has top be extracted
- * @return an Object of EffectColor
- */
- public Bitmap getBitmap(String file, int width, int height) throws IOException {
- assertNotNull("Bitmap File is Null", file);
- FileInputStream inputStream = null;
- Bitmap overlayBmp = null;
- if (!new File(file).exists())
- throw new IOException("File not Found " + file);
- try {
- final BitmapFactory.Options dbo = new BitmapFactory.Options();
- dbo.inJustDecodeBounds = true;
- dbo.outWidth = width;
- dbo.outHeight = height;
- File flPtr = new File(file);
- inputStream = new FileInputStream(flPtr);
- final Bitmap srcBitmap = BitmapFactory.decodeStream(inputStream);
- overlayBmp = Bitmap.createBitmap(srcBitmap);
- assertNotNull("Bitmap 1", srcBitmap);
- assertNotNull("Bitmap 2", overlayBmp);
- inputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return overlayBmp;
- }
-
- /**
- *This Method Create a Media Video Item with the specified params
- *
- * @return an Object of MediaVideoItem
- */
- public MediaVideoItem createMediaItem(VideoEditor videoEditor,
- String MediaId, String filename, int renderingMode) {
- MediaVideoItem mvi = null;
- try {
- mvi = new MediaVideoItem(videoEditor, MediaId, filename,
- renderingMode);
- assertNotNull("Can not create an object of MediaVideoItem", mvi);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException
- ("Can not create an object of Media Video Item with file name = "
- + filename + " Issue = " + e.toString());
- } catch (IOException e) {
- assertTrue
- ("Can not create an object of Media Video Item with file name = "
- + filename + " Issue = " + e.toString(), false);
- }
- return mvi;
- }
-
- /**
- *This Method Create a Media Image Item with the specified params
- *
- * @return an Object of MediaImageItem
- */
- public MediaImageItem createMediaItem(VideoEditor videoEditor,
- String MediaId, String filename, long duration, int renderingMode) {
- MediaImageItem mii = null;
- try {
- mii = new MediaImageItem(videoEditor, MediaId, filename, duration,
- renderingMode);
- assertNotNull("Can not create an object of MediaImageItem", mii);
-
- } catch (IllegalArgumentException e) {
- assertTrue("Can not create an object of Media Image with file name = "
- + filename + " Issue = " + e.toString(), false);
- } catch (IOException e) {
- assertTrue("Can not create an object of Media Image with file name = "
- + filename + " Issue = " + e.toString(), false);
- }
- return mii;
- }
-
- /**
- *This Method Create a Effect with the specified params
- *
- * @return an Object of EffectColor
- */
- public EffectColor createEffectItem(MediaItem mediaItem, String effectId,
- long startTime, long duration, int effectType, int colorType) {
- EffectColor effectonMVI = null;
- effectonMVI = new EffectColor(mediaItem, effectId, startTime,
- duration, effectType, colorType);
- return effectonMVI;
- }
-
- /**
- *This Method creates object of Type Transition Cross fade
- *
- * @return TransitionCrossfade object
- */
- public TransitionCrossfade createTCrossFade(String transitionId,
- MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
- int behavior) {
- Log.i("TransitionCrossfade Details === ", "Transid ID = " + transitionId +
- " Duration= " + durationMs + " Behaviour " + behavior);
-
- TransitionCrossfade transitionCF = null;
- transitionCF = new TransitionCrossfade(transitionId, afterMediaItem,
- beforeMediaItem, durationMs, behavior);
- return transitionCF;
- }
-
- /**
- *This Method creates object of Type TransitionFadeBlack
- *
- * @return TransitionFadeBlack object
- */
- public TransitionFadeBlack createTFadeBlack(String transitionId,
- MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
- int behavior) {
- TransitionFadeBlack transitionFB = null;
-
- transitionFB = new TransitionFadeBlack(transitionId, afterMediaItem,
- beforeMediaItem, durationMs, behavior);
- return transitionFB;
- }
-
- /**
- *This Method creates object of Type TransitionSliding
- *
- * @return TransitionSliding object
- */
- public TransitionSliding createTSliding(String transitionId,
- MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
- int behavior, int direction) {
- TransitionSliding transSlide = null;
- transSlide = new TransitionSliding(transitionId, afterMediaItem,
- beforeMediaItem, durationMs, behavior, direction);
- return transSlide;
- }
-
- /**
- *This Method creates object of Type TranistionAlpha
- *
- * @return TranistionAlpha object
- */
-
- public TransitionAlpha createTAlpha(String transitionId,
- MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
- int behavior, String maskFilename, int blendingPercent, boolean invert) {
- TransitionAlpha transA = null;
- transA = new TransitionAlpha(transitionId, afterMediaItem,
- beforeMediaItem, durationMs, behavior, maskFilename,
- blendingPercent, invert);
- return transA;
- }
-
- /**
- *This Method creates object of Type OverlayFrame
- *
- * @return OverlayFrame object
- */
-
- public OverlayFrame createOverlay(MediaItem mediaItem, String overlayId,
- Bitmap bitmap, long startTimeMs, long durationMs) {
- OverlayFrame overLayFrame = null;
- overLayFrame = new OverlayFrame(mediaItem, overlayId, bitmap,
- startTimeMs, durationMs);
- return overLayFrame;
- }
-
- /**
- *This Method creates object of Type AudioTrack
- *
- * @return OverlayFrame object
- */
- public AudioTrack createAudio(VideoEditor videoEditor, String audioTrackId,
- String filename) {
- AudioTrack audio = null;
- try {
- audio = new AudioTrack(videoEditor, audioTrackId, filename);
- assertNotNull("Cant not create an object of an AudioTrack " +
- audioTrackId, audio);
- } catch (IllegalArgumentException e) {
- assertTrue("Can not create object of an AudioTrack " +
- audioTrackId + " Issue = " + e.toString(), false);
- } catch (IOException e) {
- assertTrue("Can not create object of an AudioTrack " +
- audioTrackId + " Issue = " + e.toString(), false);
- }
- return audio;
- }
-
- /**
- *This Method validates the Exported Movie,as per the specified params
- * during Export
- */
-
- public void validateExport(VideoEditor videoEditor, String fileName,
- int export_height, int startTime, long endTime, int vCodec, int aCodec) {
- File tempFile = new File(fileName);
- assertEquals("Exported FileName", tempFile.exists(), true);
- final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- Log.i(TAG, "VideoCodec for file = " + fileName +
- "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
- mvi.getVideoType());
- assertEquals("Export: Video Codec Mismatch for file = " + fileName +
- "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
- vCodec, mvi.getVideoType());
-
- Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
- export_height + "\tActual VideoHeight = " + mvi.getHeight());
- assertEquals("Export height Mismatch for file " + fileName +
- "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
- export_height, mvi.getHeight());
- if (startTime == 0) {
- if (endTime != 0) {
- Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
- "\t VideoTime= " + mvi.getTimelineDuration());
- assertTrue("Timeline Duration Mismatch for file " + fileName +
- "<expected> " + (startTime + endTime) + "\t<actual> " +
- mvi.getTimelineDuration(), checkRange((startTime +
- endTime), mvi.getTimelineDuration(), 10));
- }
- } else {
- Log.i(TAG, "TimeLine Expected = " + (endTime - startTime) +
- "\t VideoTime= " + mvi.getTimelineDuration());
- assertTrue("Timeline Duration Mismatch for file " + fileName +
- "<expected> " + (endTime - startTime) + "\t<actual> " +
- mvi.getTimelineDuration(), checkRange((endTime -
- startTime), (int)mvi.getTimelineDuration(), 10));
- }
- }
-
- /**
- * @param videoEditor
- * @param fileName
- * @param export_bitrate
- * @param export_height
- * @param startTime
- * @param endTime
- * @param vCodec
- * @param aCodec
- */
- public void validateExport(VideoEditor videoEditor, String fileName,
- int export_height, int startTime, int endTime, int vCodec, int aCodec) {
- File tempFile = new File(fileName);
- assertEquals("Exported FileName", tempFile.exists(), true);
- final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- Log.i(TAG, "VideoCodec for file = " + fileName +
- "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
- mvi.getVideoType());
- assertEquals("Export: Video Codec Mismatch for file = " + fileName +
- "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
- vCodec, mvi.getVideoType());
-
- Log.i(TAG, "AudioCodec for file = " + fileName +
- "\tExpected Audio Codec = " + aCodec + "\tActual Audio Codec = " +
- mvi.getAudioType());
- assertEquals("Export: Audio Codec Mismatch for file = " + fileName +
- "\t<expected> " + aCodec + "\t<actual> " + mvi.getAudioType(),
- aCodec, mvi.getAudioType());
-
- Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
- export_height + "\tActual VideoHeight = " + mvi.getHeight());
- assertEquals("Export: height Mismatch for file " + fileName +
- "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
- export_height, mvi.getHeight());
- if (startTime == 0) {
- if (endTime != 0) {
- Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
- "\t VideoTime= " + mvi.getTimelineDuration());
- assertTrue("Export :Timeline Duration Mismatch for file " +
- fileName + "<expected> " + (startTime + endTime) +
- "\t<actual> " + mvi.getTimelineDuration(),
- checkRange((startTime + endTime), mvi.getTimelineDuration(), 10));
- }
- } else {
- Log.i(TAG, "TimeLine Expected = " + (endTime-startTime) +
- "\t VideoTime= " + mvi.getTimelineDuration());
- assertTrue("Timeline Duration Mismatch for file " + fileName +
- "<expected> " + (endTime - startTime) + "\t<actual> " +
- mvi.getTimelineDuration(), checkRange((endTime -
- startTime), mvi.getTimelineDuration(), 10));
- }
- }
-
- /**
- * Check file and deletes it.
- *
- * @param filename
- */
- public void checkDeleteExistingFile(String filename) {
- Log.i(TAG, ">>>>>>>>>>>>>>>>>>checkDeleteExistingFile = " + filename);
- if (filename != null) {
- File temp = new File(filename);
- if (temp != null && temp.exists()) {
- temp.delete();
- }
- }
- }
-
- /**
- * This method creates a Directory and filename
- *
- * @param location This is path where the file is to be created
- * "/sdcard/Output/"
- * @return Path in form of /sdcard/Output/200910100000
- */
- public String createRandomFile(String location) {
- Random randomGenerator = new Random();
- SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssS");
- Date date = new Date();
- final String filePath = location + dateFormat.format(date) +
- randomGenerator.nextInt(10);
- Log.i(TAG, ">>>>>>>>>>>>>>>>createRandomFile Location= " + location +
- "\t FilePath = " + filePath);
- return filePath;
- }
-
- /**
- * This method recursively deletes all the file and directory
- *
- * @param directory where the files are located Example = "/sdcard/Input"
- * @return boolean True if deletion is successful else False
- */
- public boolean deleteProject(File directory) {
- Log.i(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>deleteProject directory= " +
- directory.toString());
- if (directory.isDirectory()) {
- String[] filesInDirecory = directory.list();
- for (int i = 0; i < filesInDirecory.length; i++) {
- boolean success = deleteProject(new File(directory,
- filesInDirecory[i]));
- if (!success) {
- return false;
- }
- }
- }
- return directory.delete();
- }
-
- /**
- * This method compares the array of Integer from 0 - 100
- *
- * @param data set of integer values received as progress
- * @return true if sucess else false
- */
- public boolean checkProgressCBValues(int[] data) {
- boolean retFlag = false;
- for (int i = 0; i < 100; i++) {
- if (data[i] == 100) {
- retFlag = true;
- break;
- } else {
- retFlag = false;
- }
- }
- return retFlag;
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java
deleted file mode 100644
index 7dfab7d..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class MediaItemThumbnailTest extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
- private final String TAG = "MediaItemThumbailTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private VideoEditor mVideoEditor;
-
- private VideoEditorHelper mVideoEditorHelper;
-
- public MediaItemThumbnailTest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath = mVideoEditorHelper.
- createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- protected void validateThumbnail(Bitmap thumbNailBmp, int outWidth,
- int outHeight) throws Exception {
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Height", outHeight, thumbNailBmp.getHeight());
- assertEquals("Thumbnail Width", outWidth, thumbNailBmp.getWidth());
- thumbNailBmp.recycle();
- }
-
- // -----------------------------------------------------------------
- // THUMBNAIL
- // -----------------------------------------------------------------
- /**
- * To test thumbnail / frame extraction on H.263 QCIF.
- */
- @LargeTest
- public void testThumbnailForH263QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = mediaVideoItem.getHeight();
-
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on MPEG4 VGA .
- */
- @LargeTest
- public void testThumbnailForMPEG4VGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_30fps_512Kbps_0_23.3gp";
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = mediaVideoItem.getHeight();
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on MPEG4 NTSC.
- */
- @LargeTest
- public void testThumbnailForMPEG4NTSC() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on MPEG4 WVGA.
- */
- @LargeTest
- public void testThumbnailForMPEG4WVGA() throws Exception {
-
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth() * 2;
- final int outHeight = mediaVideoItem.getHeight();
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on MPEG4 QCIF.
- */
- @LargeTest
- public void testThumbnailForMPEG4QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth();
- final int outHeight = mediaVideoItem.getHeight() * 2;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on H264 QCIF.
- */
- @LargeTest
- public void testThumbnailForH264QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
-
- final int atTime = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth() * 2;
- final int outHeight = mediaVideoItem.getHeight() * 2;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on H264 VGA.
- */
- @LargeTest
- public void testThumbnailForH264VGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final int outWidth = 32;
- final int outHeight = 32;
- final int atTime = 0;
-
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
- /**
- * To test thumbnail / frame extraction on H264 WVGA.
- */
- @LargeTest
- public void testThumbnailForH264WVGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int outWidth = 64;
- final int outHeight = 64;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final long atTime = mediaVideoItem.getDuration() / 2;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on H264 854x480.
- */
- @LargeTest
- public void testThumbnailForH264854_480() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
- final int outWidth = 128;
- final int outHeight = 128;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- MediaVideoItem mediaVideoItem = null;
- mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final long atTime = mediaVideoItem.getDuration() - 1000;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on H264 960x720.
- */
- @LargeTest
- public void testThumbnailForH264HD960() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
- final int outWidth = 75;
- final int outHeight = 75;
-
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final long atTime = mediaVideoItem.getDuration() - 1000;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on H264 1080x720 .
- */
- @LargeTest
- public void testThumbnailForH264HD1080() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final long atTime = mediaVideoItem.getDuration() / 4;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * Check the thumbnail / frame extraction precision at 0,100 and 200 ms
- */
- @LargeTest
- public void testThumbnailForH264VGADifferentDuration() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final int atTime = 0;
- final int atTime1 = 100;
- final int atTime2 = 200;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth();
- final int outHeight = mediaVideoItem.getHeight();
-
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
- // get Thumbnail @ 100ms
- final Bitmap thumbNailBmpAt100 =
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime1);
- validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
-
- // get Thumbnail @ 200ms
- final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
- outWidth, outHeight, atTime2);
- validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
- }
-
- /**
- *Check the thumbnail / frame extraction precision at
- * FileDuration,FileDuration/2 + 100 andFileDuration/2 + 200 ms
- */
- @LargeTest
- public void testThumbnailForMP4VGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- final int outWidth = mediaVideoItem.getWidth();
- final int outHeight = mediaVideoItem.getHeight();
- final long atTime = mediaVideoItem.getDuration() / 2;
- final long atTime1 = atTime + 100;
- final long atTime2 = atTime + 200;
-
- // get Thumbnail @ duration/2
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
- // get Thumbnail @ duration/2 + 100ms
- final Bitmap thumbNailBmpAt100 = mediaVideoItem.getThumbnail(
- outWidth, outHeight, atTime1);
- validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
-
- // get Thumbnail @ duration/2 + 200ms
- final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
- outWidth, outHeight, atTime2);
- validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
- }
-
- /**
- * Check the thumbnail / frame extraction on JPEG file
- */
- @LargeTest
- public void testThumbnailForImage() throws Exception {
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int mediaDuration = 1000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- int outWidth = 0;
- int outHeight = 0;
-
- final MediaImageItem mii = mVideoEditorHelper.createMediaItem(
- mVideoEditor, "m1", imageItemFilename, mediaDuration, renderingMode);
- assertNotNull("Media Image Item is Null", mii);
- outWidth = mii.getWidth() / 2;
- outHeight = mii.getHeight() / 2;
-
- final Bitmap thumbNailBmp = mii.getThumbnail(outWidth,
- outHeight, mediaDuration);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
- /**
- *To test ThumbnailList for H263 QCIF
- */
- @LargeTest
- public void testThumbnailListH263QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- final int startTime = 0;
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = mediaVideoItem.getWidth() / 4;
- final int outHeight = mediaVideoItem.getHeight() / 4;
- final long endTime = mediaVideoItem.getDuration() / 2;
-
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
- outWidth, outHeight, startTime, endTime, tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for MPEG4 QCIF
- */
- @LargeTest
- public void testThumbnailListMPEG4QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final long startTime = mediaVideoItem.getDuration() / 2;
- final long endTime = mediaVideoItem.getDuration();
-
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
- outWidth, outHeight, startTime, endTime, tnCount);
-
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for H264 VGA
- */
- @LargeTest
- public void testThumbnailListH264VGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final long startTime = mediaVideoItem.getDuration() / 3;
- final long endTime = mediaVideoItem.getDuration() / 2;
-
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
- outWidth, outHeight, startTime, endTime, tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for H264 WVGA
- */
- @LargeTest
- public void testThumbnailListH264WVGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final long startTime = mediaVideoItem.getDuration() / 3;
- final long endTime = mediaVideoItem.getDuration() / 2;
-
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
- outWidth, outHeight, startTime, endTime, tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for H264 VGA ,Time exceeding file duration
- */
- @LargeTest
- public void testThumbnailH264VGAExceedingFileDuration() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- boolean flagForException = false;
- int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth() / 2;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- final long atTime = mediaVideoItem.getDuration() + 2000;
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Exception in Extracting thumbanil with Invalid Time",
- flagForException);
- }
-
- /**
- *To test ThumbnailList for VGA Image
- */
- @LargeTest
- public void testThumbnailListVGAImage() throws Exception {
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemDuration = 10000;
- final int startTime = 0;
- final int endTime = 0;
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- imageItemFilename, imageItemDuration, renderingMode);
- final int outWidth = mediaImageItem.getWidth() / 2;
- final int outHeight = mediaImageItem.getHeight() / 2;
-
- final Bitmap thumbNailBmp[] = mediaImageItem.getThumbnailList
- (outWidth, outHeight, startTime, endTime, tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for Invalid file path
- */
- @LargeTest
- public void testThumbnailForInvalidFilePath() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "/sdcard/abc.jpg";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try{
- final MediaImageItem mii = new MediaImageItem(mVideoEditor, "m1",
- imageItemFileName, 3000, renderingMode);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- } catch (IOException e) {
- flagForException = true;
- }
- assertTrue(" Invalid File Path", flagForException);
- }
-
- /**
- * To test thumbnail / frame extraction with setBoundaries
- */
- @LargeTest
- public void testThumbnailForMPEG4WVGAWithSetBoundaries() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
- final int atTime = 10000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- mediaVideoItem.setExtractBoundaries(1000,
- (mediaVideoItem.getDuration() - 21000));
-
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- *To test ThumbnailList for H264 WVGA with setExtractboundaries
- */
- @LargeTest
- public void testThumbnailListForH264WVGAWithSetBoundaries() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_1_17.mp4";
- final int thumbNailStartTime = 10000;
- final int thumbNailEndTime = 12000;
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
-
- mediaVideoItem.setExtractBoundaries(10000, 12000);
-
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList
- (outWidth, outHeight, thumbNailStartTime, thumbNailEndTime,
- tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertTrue("Thumbnail Size", (thumbNailBmp.length > 0) ? true : false);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for H264 WVGA with count > frame available
- */
- @LargeTest
- public void testThumbnailListForH264WVGAWithCount() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int tnCount = 70;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
-
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
- final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
- final long thumbNailEndTime = thumbNailStartTime + 4000;
- Bitmap thumbNailBmp[] = null;
- boolean flagForException = false;
- try{
- thumbNailBmp = mediaVideoItem.getThumbnailList(outWidth, outHeight,
- thumbNailStartTime, thumbNailEndTime, tnCount);
- }catch (Exception e){
- assertTrue("Unable to get Thumbnail list", flagForException);
- }
- if (thumbNailBmp.length <= tnCount) {
- flagForException = true;
- }
- assertTrue("Thumbnail count more than asked", flagForException);
- }
-
- /**
- *To test ThumbnailList for H264 WVGA with startTime > End Time
- */
- @LargeTest
- public void testThumbnailListH264WVGAWithStartGreaterEnd() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int tnCount = 10;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
- final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
- final long thumbNailEndTime = thumbNailStartTime - 1000;
- try{
- mediaVideoItem.getThumbnailList(outWidth, outHeight,
- thumbNailStartTime, thumbNailEndTime, tnCount);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail Extraction where start time > end time",
- flagForException);
- }
-
- /**
- *To test ThumbnailList for H264 WVGA with startTime = End Time
- */
- @LargeTest
- public void testThumbnailListH264WVGAWithStartEqualEnd() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int tnCount = 1;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
- final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
- final long thumbNailEndTime = thumbNailStartTime;
- final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(outWidth,
- outHeight, thumbNailStartTime, thumbNailEndTime, tnCount);
- assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
- assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
- for (int i = 0; i < thumbNailBmp.length; i++) {
- validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
- thumbNailBmp[i] = null;
- }
- }
-
- /**
- *To test ThumbnailList for file where video duration is less
- * than file duration.
- */
- @LargeTest
- public void testThumbnailForVideoDurationLessFileDuration() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = (mediaVideoItem.getHeight() / 2);
- final long atTime = mediaVideoItem.getDuration() - 2000;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
- }
-
- /**
- *To test ThumbnailList for file which has video part corrupted
- */
- @LargeTest
- public void testThumbnailWithCorruptedVideoPart() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "corrupted_H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
-
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth();
- final int outHeight = mediaVideoItem.getHeight() * 2;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail
- (outWidth, outHeight, mediaVideoItem.getDuration()/2);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Corrupted File cannot be read", flagForException);
- }
-
- /**
- * Check the thumbnail / frame list extraction for Height as Negative Value
- */
- @LargeTest
- public void testThumbnailWithNegativeHeight() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = -1;
- final long thumbNailStartTime =
- mediaVideoItem.getBoundaryBeginTime()/2;
- final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
- mediaVideoItem.getThumbnailList(outWidth, outHeight,
- thumbNailStartTime, thumbNailEndTime, tnCount);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail List with negative Height", flagForException);
- }
-
- /**
- * Check the thumbnail for Height as Zero
- */
- @LargeTest
- public void testThumbnailWithHeightAsZero() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int atTime = 100;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = -1;
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail List with Zero Height", flagForException);
- }
-
- /**
- * Check the thumbnail for Height = 10
- */
- @LargeTest
- public void testThumbnailWithHeight() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int atTime = 1000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = (mediaVideoItem.getWidth() / 2);
- final int outHeight = 10;
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * Check the thumbnail / frame list extraction for Width as Negative Value
- */
- @LargeTest
- public void testThumbnailWithNegativeWidth() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int tnCount = 10;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = -1;
- final int outHeight = mediaVideoItem.getHeight();
- final long thumbNailStartTime =
- mediaVideoItem.getBoundaryBeginTime()/2;
- final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
- mediaVideoItem.getThumbnailList(outWidth, outHeight, thumbNailStartTime,
- thumbNailEndTime, tnCount);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail List with negative Height", flagForException);
- }
-
- /**
- * Check the thumbnail / frame list extraction for Width zero
- */
- @LargeTest
- public void testThumbnailWithWidthAsZero() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int atTime = 1000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try {
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = 0;
- final int outHeight = mediaVideoItem.getHeight() / 2;
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail List with Zero Width", flagForException);
- }
-
- /**
- * Check the thumbnail for Width = 10
- */
- @LargeTest
- public void testThumbnailWithWidth() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- final int atTime = 1000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = 10;
- final int outHeight = mediaVideoItem.getHeight();
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
- outHeight, atTime);
- validateThumbnail(thumbNailBmp, outWidth, outHeight);
- }
-
- /**
- * To test thumbnail / frame extraction on MPEG4 (time beyond file duration).
- */
- @LargeTest
- public void testThumbnailMPEG4withMorethanFileDuration() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
- boolean flagForException = false;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename, renderingMode);
- final int outWidth = mediaVideoItem.getWidth()/2;
- final int outHeight = mediaVideoItem.getHeight()/2;
- final long atTime = mediaVideoItem.getDuration() + 100;
- try{
- final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
- outHeight, atTime);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Thumbnail duration is more than file duration",
- flagForException);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java
deleted file mode 100644
index 34cf9f0..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-import com.android.mediaframeworktest.MediaProfileReader;
-
-public class MediaPropertiesTest extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
- private final String TAG = "MediaPropertiesTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private VideoEditor mVideoEditor;
-
- private VideoEditorHelper mVideoEditorHelper;
-
- public MediaPropertiesTest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path,
- // where all project related files will be stored.
- final String projectPath = mVideoEditorHelper.
- createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- protected void validateVideoProperties(int aspectRatio, int fileType,
- int videoCodecType, int duration, int videoBitrate, int fps,
- int videoProfile, int videoLevel, int width, int height, int audioCodecType,
- int audioSamplingFrequency, int audioChannel, int audioBitrate,
- MediaVideoItem mvi) throws Exception {
- assertEquals("Aspect Ratio Mismatch", aspectRatio, mvi.getAspectRatio());
- assertEquals("File Type Mismatch", fileType, mvi.getFileType());
- assertEquals("VideoCodec Mismatch", videoCodecType, mvi.getVideoType());
-
- assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
- duration, mvi.getDuration(), 10));
- assertEquals("Video Profile " + mvi.getVideoProfile(), videoProfile,
- mvi.getVideoProfile());
- assertEquals("Video Level " + mvi.getVideoLevel(), videoLevel,
- mvi.getVideoLevel());
- assertEquals("Video height " + mvi.getHeight(), height, mvi.getHeight());
- assertEquals("Video width " + mvi.getWidth(), width, mvi.getWidth());
- /** Check FPS with 10% range */
- assertTrue("fps Mismatch" + mvi.getFps(),
- mVideoEditorHelper.checkRange(fps, mvi.getFps(), 10));
-
- assertEquals("AudioType Mismatch ", audioCodecType, mvi.getAudioType());
- assertEquals("Audio Sampling " + mvi.getAudioSamplingFrequency(),
- audioSamplingFrequency, mvi.getAudioSamplingFrequency());
- // PV SW AAC codec always returns number of channels as Stereo.
- // So we do not assert for number of audio channels for AAC_LC
- if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
- assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel,
- mvi.getAudioChannels());
- }
- }
-
- protected void validateAudioProperties(int audioCodecType, int duration,
- int audioSamplingFrequency, int audioChannel, int audioBitrate,
- AudioTrack aT) throws Exception {
- assertEquals("AudioType Mismatch ", audioCodecType, aT.getAudioType());
- assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
- duration, aT.getDuration(), 10));
- assertEquals("Audio Sampling " + aT.getAudioSamplingFrequency(),
- audioSamplingFrequency, aT.getAudioSamplingFrequency());
- // PV SW AAC codec always returns number of channels as Stereo.
- // So we do not assert for number of audio channels for AAC_LC
- if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
- assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel,
- aT.getAudioChannels());
- }
- }
-
- protected void validateImageProperties(int aspectRatio, int fileType,
- int width, int height, MediaImageItem mii)
- throws Exception {
- assertEquals("Aspect Ratio Mismatch", aspectRatio, mii.getAspectRatio());
- assertEquals("File Type Mismatch", fileType, mii.getFileType());
- assertEquals("Image height " + mii.getHeight(), height, mii.getHeight());
- assertEquals("Image width " + mii.getWidth(), width, mii.getWidth());
- }
-
-
- /**
- *To test Media Properties for file MPEG4 854 x 480
- */
- @LargeTest
- public void testPropertiesMPEG4854_480() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_MPEG4;
- final int duration = 26933;
- final int videoBitrate = 319000;
- final int audioBitrate = 48000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 16000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
- final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
- final int width = 854;
- final int height = MediaProperties.HEIGHT_480;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
-
- /**
- *To test Media Properties for file MPEG4 WVGA
- */
- @LargeTest
- public void testPropertiesMPEGWVGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_MPEG4;
- final int duration = 26933;
- final int videoBitrate = 384000;
- final int audioBitrate = 12800;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AMRNB;
- final int audioSamplingFrequency = 8000;
- final int audioChannel = 1;
- final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
- final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
- final int width = 800;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test media properties for MPEG4 720x480 (NTSC) + AAC file.
- */
- @LargeTest
- public void testPropertiesMPEGNTSC() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_MPEG4;
- final int duration = 26866;
- final int videoBitrate = 403000;
- final int audioBitrate = 160000;
- final int fps = 30;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 48000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
- final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
- final int width = 720;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file MPEG4 VGA
- */
- @LargeTest
- public void testPropertiesMPEGVGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_MPEG4;
- final int duration = 26933;
- final int videoBitrate = 533000;
- final int audioBitrate = 128000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 48000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
- final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
- final int width = 640;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file MPEG4 QCIF
- */
- @LargeTest
- public void testPropertiesMPEGQCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "MPEG4_SP_176x144_12fps_92kbps_AMRNB_8KHz_12.2kbps_m_0_27.3gp";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
- final int fileType = MediaProperties.FILE_3GP;
- final int videoCodecType = MediaProperties.VCODEC_MPEG4;
- final int duration = 27000;
- final int videoBitrate = 384000;
- final int audioBitrate = 12200;
- final int fps = 12;
- final int audioCodecType = MediaProperties.ACODEC_AMRNB;
- final int audioSamplingFrequency = 8000;
- final int audioChannel = 1;
- final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
- final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
- final int width = 176;
- final int height = MediaProperties.HEIGHT_144;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To To test media properties for H263 176x144 (QCIF) + AAC (mono) file.
- */
- @LargeTest
- public void testPropertiesH263QCIF() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_16kHz_32kbps_m_0_26.3gp";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
- final int fileType = MediaProperties.FILE_3GP;
- final int videoCodecType = MediaProperties.VCODEC_H263;
- final int duration = 26933;
- final int videoBitrate = 384000;
- final int audioBitrate = 64000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 16000;
- final int audioChannel = 1;
- final int videoProfile = MediaProperties.H263Profile.H263ProfileBaseline;
- final int videoLevel = MediaProperties.H263Level.H263Level10;
- final int width = 176;
- final int height = MediaProperties.HEIGHT_144;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file H264 VGA
- */
- @LargeTest
- public void testPropertiesH264VGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int fileType = MediaProperties.FILE_3GP;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77600;
- final int videoBitrate = 745000;
- final int audioBitrate = 64000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 48000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 640;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file H264 NTSC
- */
- @LargeTest
- public void testPropertiesH264NTSC() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_720x480_25fps_256kbps_AMRNB_8khz_12.2kbps_m_0_26.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 26880;
- final int videoBitrate = 244000;
- final int audioBitrate = 12200;
- final int fps = 25;
- final int audioCodecType = MediaProperties.ACODEC_AMRNB;
- final int audioSamplingFrequency = 8000;
- final int audioChannel = 1;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 720;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test media properties for H264 800x480 (WVGA) + AAC file.
- */
- @LargeTest
- public void testPropertiesH264WVGA() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77466;
- final int videoBitrate = 528000;
- final int audioBitrate = 38000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 24000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 800;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file H264 HD1280
- */
- @LargeTest
- public void testPropertiesH264HD1280() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_1280x720_15fps_512kbps_AACLC_16khz_48kbps_s_1_17.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77600;
- final int videoBitrate = 606000;
- final int audioBitrate = 48000;
- final int fps = 15;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 16000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 1280;
- final int height = MediaProperties.HEIGHT_720;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test media properties for H264 1080x720 + AAC file
- */
- @LargeTest
- public void testPropertiesH264HD1080WithAudio() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77500;
- final int videoBitrate = 1190000;
- final int audioBitrate = 64000;
- final int fps = 10;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 44100;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 1080;
- final int height = MediaProperties.HEIGHT_720;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for file WMV - Unsupported type
- */
- @LargeTest
- public void testPropertiesWMVFile() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "WMV_V7_640x480_15fps_512Kbps_wma_V9_44khz_48Kbps_s_1_30.wmv";
- boolean flagForException = false;
- if (MediaProfileReader.getWMVEnable() == false) {
- flagForException = true;
- } else {
- try {
- new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- } catch (IOException e) {
- flagForException = true;
- }
- }
- assertTrue("Media Properties for a WMV File -- Unsupported file type",
- flagForException);
- }
-
- /**
- *To test media properties for H.264 Main/Advanced profile.
- */
- @LargeTest
- public void testPropertiesH264MainLineProfile() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH
- + "H264_MP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int fileType = MediaProperties.FILE_MP4;
- final int duration = 77500;
- final int videoBitrate = 800000;
- final int audioBitrate = 192000;
- final int fps = 25;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 48000;
- final int audioChannel = 2;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileMain;
- final int videoLevel = MediaProperties.H264Level.H264Level31;
- final int width = 960;
- final int height = MediaProperties.HEIGHT_720;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-
- }
-
- /**
- *To test Media Properties for non existing file.
- */
- @LargeTest
- public void testPropertiesForNonExsitingFile() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH + "abc.3gp";
- boolean flagForException = false;
-
- try {
- new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- } catch (IOException e) {
- flagForException = true;
- }
- assertTrue("Media Properties for non exsisting file", flagForException);
- }
-
- /**
- *To test Media Properties for file H264 HD1080
- */
- @LargeTest
- public void testPropertiesH264HD1080WithoutAudio() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77366;
- final int videoBitrate = 859000;
- final int audioBitrate = 0;
- final int fps = 30;
- final int audioCodecType = -1;
- final int audioSamplingFrequency = 0;
- final int audioChannel = 0;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 1080;
- final int height = MediaProperties.HEIGHT_720;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
- validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
- videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
- audioSamplingFrequency, audioChannel, audioBitrate, mvi);
- }
-
- /**
- *To test Media Properties for Image file of JPEG Type
- */
- @LargeTest
- public void testPropertiesVGAImage() throws Exception {
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemDuration = 10000;
- final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int fileType = MediaProperties.FILE_JPEG;
- final int width = 640;
- final int height = MediaProperties.HEIGHT_480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaImageItem mii = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
- renderingMode);
- validateImageProperties(aspectRatio, fileType, width, height, mii);
- }
-
- /**
- *To test Media Properties for Image file of PNG Type
- */
- @LargeTest
- public void testPropertiesPNG() throws Exception {
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.png";
- final int imageItemDuration = 10000;
- final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int fileType = MediaProperties.FILE_PNG;
- final int width = 640;
- final int height = 480;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mii = mVideoEditorHelper.createMediaItem
- (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
- renderingMode);
- validateImageProperties(aspectRatio, fileType, width, height, mii);
- }
-
- /**
- *To test Media Properties for file GIF - Unsupported type
- */
- @LargeTest
- public void testPropertiesGIFFile() throws Exception {
-
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.gif";
- final int imageItemDuration = 10000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- try {
- new MediaImageItem(mVideoEditor, "m1", imageItemFilename,
- imageItemDuration, renderingMode);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Properties for a GIF File -- Unsupported file type",
- flagForException);
- }
-
- /**
- *To test Media Properties for file Text file named as 3GP
- */
- @LargeTest
- public void testPropertiesofDirtyFile() throws Exception {
-
- final String videoItemFilename = INPUT_FILE_PATH +
- "Text_FileRenamedTo3gp.3gp";
- boolean flagForException = false;
-
- try {
- new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Properties for a Dirty File ",
- flagForException);
- }
-
- /**
- *To test Media Properties for file name as NULL
- */
- @LargeTest
- public void testPropertieNULLFile() throws Exception {
- final String videoItemFilename = null;
- boolean flagForException = false;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- try {
- new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
- renderingMode);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Properties for NULL File ",
- flagForException);
- }
-
- /**
- *To test Media Properties for file which is of type MPEG2
- */
- @LargeTest
- public void testPropertiesMPEG2File() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "MPEG2_640x480_30fps_192kbps_1_5.mp4";
- boolean flagForException = false;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- try {
- new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
- renderingMode);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Properties for a MPEG2 File --Unsupported file type",
- flagForException);
- }
-
- /**
- *To test Media Properties for file without Video only Audio
- */
- @LargeTest
- public void testProperties3GPWithoutVideoMediaItem() throws Exception {
- final String audioFilename = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- try {
- new MediaVideoItem(mVideoEditor, "m1", audioFilename,
- renderingMode);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Exception in Creaing Media Video item object without video",
- flagForException);
- }
-
- /**
- *To test media properties for Audio Track file. (No Video, AAC Audio)
- */
- @LargeTest
- public void testProperties3GPWithoutVideoAudioTrack() throws Exception {
-
- final String audioFilename = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- final int duration = 77554;
- final int audioBitrate = 384000;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 44100;
- final int audioChannel = 2;
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio
- (mVideoEditor, "a1", audioFilename);
-
- validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
- audioChannel, audioBitrate, audioTrack);
- }
-
- /**
- *To test media properties for Audio Track file. MP3 file
- */
- @LargeTest
- public void testPropertiesMP3AudioTrack() throws Exception {
-
- final String audioFilename = INPUT_FILE_PATH +
- "MP3_48KHz_128kbps_s_1_17.mp3";
- final int duration = 77640;
- final int audioBitrate = 128000;
- final int audioCodecType = MediaProperties.ACODEC_MP3;
- final int audioSamplingFrequency = 48000;
- final int audioChannel = 2;
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio
- (mVideoEditor, "a1", audioFilename);
-
- validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
- audioChannel, audioBitrate, audioTrack);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java
deleted file mode 100644
index 6e520c3..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java
+++ /dev/null
@@ -1,2751 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.util.List;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.ExtractAudioWaveformProgressListener;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-
-import android.util.Log;
-import java.lang.annotation.Annotation;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class VideoEditorAPITest extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
- private final String TAG = "VideoEditorTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private final String PROJECT_CLASS_NAME =
- "android.media.videoeditor.VideoEditorImpl";
- private VideoEditor mVideoEditor;
- private VideoEditorHelper mVideoEditorHelper;
-
- public VideoEditorAPITest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath = mVideoEditorHelper.
- createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- /**
- * To Test Creation of Media Video Item.
- */
- @LargeTest
- public void testMediaVideoItem() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode =
- MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
-
- assertTrue("Media Video ID",
- mediaVideoItem1.getId().equals("mediaVideoItem1"));
- assertTrue("Media Video Filename",
- mediaVideoItem1.getFilename().equals(videoItemFileName));
- assertEquals("Media Video Rendering Mode",
- videoItemRenderingMode, mediaVideoItem1.getRenderingMode());
- assertEquals("Media Video Item Duration", mediaVideoItem1.getDuration(),
- mediaVideoItem1.getTimelineDuration());
- assertEquals("Media Video Overlay", 0,
- mediaVideoItem1.getAllOverlays().size());
- assertEquals("Media Video Effect", 0,
- mediaVideoItem1.getAllEffects().size());
- assertNull("Media Video Begin transition",
- mediaVideoItem1.getBeginTransition());
- assertNull("Media Video End transition",
- mediaVideoItem1.getEndTransition());
- mediaVideoItem1.setExtractBoundaries(1000,11000);
- boolean flagForException = false;
- if (mediaVideoItem1.getDuration() !=
- mediaVideoItem1.getTimelineDuration()) {
- flagForException = true;
- }
- assertTrue("Media Video Item Duration & Timeline are same",
- flagForException );
- }
-
- /**
- * To test creation of Media Video Item with Set Extract Boundaries With Get
- * the Begin and End Time.
- */
- @LargeTest
- public void testMediaVideoItemExtractBoundaries() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- mediaVideoItem1.setExtractBoundaries(1000, 11000);
- assertEquals("Media Item Duration = StoryBoard Duration",
- mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
- try {
- mediaVideoItem1.setExtractBoundaries(0, 100000000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Set Extract with Invalid Values endTime > FileDuration",
- flagForException);
-
- flagForException = false;
- try {
- mediaVideoItem1.setExtractBoundaries(100000000, 11000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Set Extract with Invalid Values startTime > endTime",
- flagForException);
-
- flagForException = false;
- try {
- mediaVideoItem1.setExtractBoundaries(0, 0);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Set Extract with Invalid Values startTime = endTime",
- flagForException);
-
- mediaVideoItem1.setExtractBoundaries(1000, 10000);
- assertTrue("Media Item Duration is still the same",
- (mediaVideoItem1.getTimelineDuration() ==
- (mediaVideoItem1.getBoundaryEndTime()-
- mediaVideoItem1.getBoundaryBeginTime())) ? true : false);
-
- mediaVideoItem1.setExtractBoundaries(1,mediaVideoItem1.getDuration()-1);
- assertEquals("Media Item Start Time", 1,
- mediaVideoItem1.getBoundaryBeginTime());
- assertEquals("Media Item End Time", (mediaVideoItem1.getDuration() - 1),
- mediaVideoItem1.getBoundaryEndTime());
-
- mediaVideoItem1.setExtractBoundaries(1, mediaVideoItem1.getDuration());
- assertEquals("Media Item Duration = StoryBoard Duration",
- mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-
- mediaVideoItem1.setExtractBoundaries(0,mediaVideoItem1.getDuration()/2);
- assertEquals("Media Item Duration = StoryBoard Duration",
- mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-
- mediaVideoItem1.setExtractBoundaries(0, -1);
- assertEquals("Media Item Duration = StoryBoard Duration",
- mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
- }
-
- /**
- * To test creation of Media Video Item with Set and Get rendering Mode
- */
- @LargeTest
- public void testMediaVideoItemRenderingModes() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode= MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_CROPPING);
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_CROPPING,
- mediaVideoItem1.getRenderingMode());
- try {
- mediaVideoItem1.setRenderingMode(
- MediaItem.RENDERING_MODE_CROPPING + 911);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Item Invalid rendering Mode", flagForException);
- flagForException = false;
- try {
- mediaVideoItem1.setRenderingMode(
- MediaItem.RENDERING_MODE_BLACK_BORDER - 11);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Item Invalid rendering Mode", flagForException);
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_CROPPING,
- mediaVideoItem1.getRenderingMode());
- mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_STRETCH,
- mediaVideoItem1.getRenderingMode());
- }
-
-
- /**
- * To Test the Media Video API : Set Audio Volume, Get Audio Volume and Mute
- */
- @LargeTest
- public void testMediaVideoItemAudioFeatures() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- mediaVideoItem1.setVolume(77);
- assertEquals("Updated Volume is 77", 77, mediaVideoItem1.getVolume());
-
- mediaVideoItem1.setMute(true);
- assertTrue("Audio must be Muted", mediaVideoItem1.isMuted());
-
- mediaVideoItem1.setVolume(78);
- assertEquals("Updated Volume is 78", 78, mediaVideoItem1.getVolume());
- assertTrue("Audio must be Muted", mediaVideoItem1.isMuted());
-
- try {
- mediaVideoItem1.setVolume(1000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid Set Volume", flagForException);
-
- mediaVideoItem1.setMute(false);
- assertFalse("Audio must be Un-Muted", mediaVideoItem1.isMuted());
-
- mediaVideoItem1.setVolume(0);
- assertFalse("Audio must be Un-Muted", mediaVideoItem1.isMuted());
-
- flagForException = false;
- try {
- mediaVideoItem1.setVolume(-1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid Set Volume", flagForException);
-
- mediaVideoItem1.setVolume(100);
- assertEquals("MediaItem Volume", 100, mediaVideoItem1.getVolume());
- try {
- mediaVideoItem1.setVolume(101);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid Set Volume", flagForException);
- assertEquals("MediaItem Volume", 100, mediaVideoItem1.getVolume());
- }
-
- /**
- * To Test the Media Video API : GetWaveFormData and
- * extractAudioWaveFormData
- */
-
- @LargeTest
- public void testMediaVideoItemGetWaveformData() throws Exception {
-
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- assertNull("WaveForm data", mediaVideoItem1.getWaveformData());
- final int[] progressWaveform = new int[105];
-
- mediaVideoItem1.extractAudioWaveform(new
- ExtractAudioWaveformProgressListener() {
- int i = 0;
- public void onProgress(int progress) {
- Log.i("WaveformData","progress=" +progress);
- progressWaveform[i++] = progress;
- }
- });
- assertTrue("Progress of WaveForm data", mVideoEditorHelper
- .checkProgressCBValues(progressWaveform));
- assertNotNull("WaveForm data", mediaVideoItem1.getWaveformData());
- assertTrue("WaveForm Frame Duration",
- (mediaVideoItem1.getWaveformData().getFrameDuration() > 0?
- true : false));
- assertTrue("WaveForm Frame Count",
- (mediaVideoItem1.getWaveformData().getFramesCount() > 0 ?
- true : false));
- assertTrue("WaveForm Gain",
- (mediaVideoItem1.getWaveformData().getFrameGains().length > 0 ?
- true : false));
-
- }
-
- /**
- * To Test the Media Video API : Get Effect, GetAllEffects, remove Effect
- */
-
- @LargeTest
- public void testMediaVideoItemEffect() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem1 = mVideoEditorHelper.
- createMediaItem(mVideoEditor, "mediaVideoItem1", videoItemFileName,
- videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- assertTrue("Effect List Size",
- (mediaVideoItem1.getAllEffects().size() == 0) ? true : false);
- assertNull("Effect Item by ID", mediaVideoItem1.getEffect("xyx"));
-
- final EffectColor effectColor = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "Effecton MVi1", 0, 4000, EffectColor.TYPE_GRADIENT,
- EffectColor.GRAY);
- mediaVideoItem1.addEffect(effectColor);
-
- assertTrue("Effect List Size", (mediaVideoItem1.
- getAllEffects().size() == 1) ? true : false);
- assertEquals("Effect Item by Valid ID", effectColor,
- mediaVideoItem1.getEffect(effectColor.getId()));
- assertNull("Effect Item by Invalid ID",
- mediaVideoItem1.getEffect("xyz"));
- assertNull("Effect Item by Invalid ID",
- mediaVideoItem1.removeEffect("effectId"));
- assertTrue("Effect List Size",
- (mediaVideoItem1.getAllEffects().size() == 1) ? true : false);
- assertEquals("Effect Removed", effectColor,
- mediaVideoItem1.removeEffect(effectColor.getId()));
- assertTrue("Effect List Size",
- (mediaVideoItem1.getAllEffects().size() == 0) ? true : false);
- assertNull("Effect Item by ID", mediaVideoItem1.getEffect("effectId"));
- }
-
- /**
- * To Test the Media Video API : Get Before and after transition
- */
-
- @LargeTest
- public void testMediaVideoItemTransitions() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- assertNull("Begin Transition", mediaVideoItem1.getBeginTransition());
- assertNull("End Transition", mediaVideoItem1.getEndTransition());
-
- TransitionFadeBlack transition1 =
- mVideoEditorHelper.createTFadeBlack("transition1", mediaVideoItem1,
- null, 0, Transition.BEHAVIOR_SPEED_UP);
- mVideoEditor.addTransition(transition1);
- assertEquals("Begin transition", transition1,
- mediaVideoItem1.getEndTransition());
-
- assertNotNull("End Transition", mediaVideoItem1.getEndTransition());
- assertTrue(mediaVideoItem1.
- getEndTransition().getId().equals(transition1.getId()));
- assertTrue(mediaVideoItem1.getEndTransition().getDuration() ==
- transition1.getDuration() ? true : false);
- assertTrue(mediaVideoItem1.getEndTransition().getBehavior() ==
- transition1.getBehavior() ? true : false);
-
- TransitionFadeBlack transition2 = mVideoEditorHelper.createTFadeBlack(
- "transition2", null,mediaVideoItem1, 0, Transition.BEHAVIOR_LINEAR);
- mVideoEditor.addTransition(transition2);
- assertNotNull("Begin transition", mediaVideoItem1.getBeginTransition());
- assertEquals("End Transition", transition2,
- mediaVideoItem1.getBeginTransition());
- assertTrue(mediaVideoItem1.
- getBeginTransition().getId().equals(transition2.getId()));
- assertTrue(mediaVideoItem1. getBeginTransition().getDuration() ==
- transition2.getDuration() ? true : false);
- assertTrue(mediaVideoItem1.getBeginTransition().getBehavior() ==
- transition2.getBehavior() ? true : false);
- }
-
- /**
- * To Test the Media Video API : Get All Overlay, Get Overlay and remove Overlay
- *
- */
-
- @LargeTest
- public void testMediaVideoItemOverlays() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String overlayItemFileName = INPUT_FILE_PATH +
- "IMG_176x144_Overlay1.png";
- final int videoItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- assertTrue("Overlay List Size",
- (mediaVideoItem1.getAllOverlays().size() == 0) ? true : false);
- assertNull("Overlay Item by ID", mediaVideoItem1.getOverlay("xyz"));
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayItemFileName,
- 176, 144);
- final OverlayFrame overlayFrame = mVideoEditorHelper.createOverlay(
- mediaVideoItem1, "overlayId", mBitmap, 5000, 5000);
- mediaVideoItem1.addOverlay(overlayFrame);
-
- assertTrue("Overlay List Size",
- (mediaVideoItem1.getAllOverlays().size() == 1) ? true : false);
- assertEquals("Overlay Item by Valid ID", overlayFrame, mediaVideoItem1
- .getOverlay(overlayFrame.getId()));
- assertNull("Overlay Item by Invalid ID",
- mediaVideoItem1.getOverlay("xyz"));
- assertNull("Overlay Item by Invalid ID",
- mediaVideoItem1.removeOverlay("xyz"));
- assertTrue("Overlay List Size",
- (mediaVideoItem1.getAllOverlays().size() == 1) ? true : false);
- assertEquals("Overlay Removed", overlayFrame,
- mediaVideoItem1.removeOverlay(overlayFrame.getId()));
- assertTrue("Overlay List Size",
- (mediaVideoItem1.getAllOverlays().size() == 0) ? true : false);
- assertNull("Overlay Item by ID",mediaVideoItem1.getOverlay("effectId"));
- }
-
- /**
- * To Test Creation of Media Image Item.
- */
- @LargeTest
- public void testMediaImageItem() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- assertTrue("Media Image ID",
- mediaImageItem1.getId().equals("mediaImageItem1"));
- assertTrue("Media IMage Filename",
- mediaImageItem1.getFilename().equals(imageItemFileName));
- assertEquals("Media Image Rendering Mode",
- imageItemRenderingMode, mediaImageItem1.getRenderingMode());
- assertEquals("Media Image Item Duration", mediaImageItem1.getDuration(),
- mediaImageItem1.getTimelineDuration());
- assertEquals("Media Image Overlay", 0,
- mediaImageItem1.getAllOverlays().size());
- assertEquals("Media Image Effect", 0,
- mediaImageItem1.getAllEffects().size());
- assertNull("Media Image Begin transition",
- mediaImageItem1.getBeginTransition());
- assertNull("Media Image End transition",
- mediaImageItem1.getEndTransition());
- assertEquals("Media Image Scaled Height", MediaProperties.HEIGHT_720,
- mediaImageItem1.getScaledHeight());
- assertEquals("Media Image Scaled Width", 960,
- mediaImageItem1.getScaledWidth());
- assertEquals("Media Image Aspect Ratio", MediaProperties.ASPECT_RATIO_4_3,
- mediaImageItem1.getAspectRatio());
- assertNotNull("Media Image Thumbnail",
- mediaImageItem1.getThumbnail(960, MediaProperties.HEIGHT_720, 2000));
- }
-
- /**
- * To Test the Media Image API : Get and Set rendering Mode
- */
- @LargeTest
- public void testMediaImageItemRenderingModes() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, imageItemRenderingMode, 5000);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- mediaImageItem1.setRenderingMode(MediaItem.RENDERING_MODE_CROPPING);
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_CROPPING, mediaImageItem1.getRenderingMode());
- try {
- mediaImageItem1.setRenderingMode(
- MediaItem.RENDERING_MODE_CROPPING + 911);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Item Invalid rendering Mode", flagForException);
-
- flagForException = false;
- try {
- mediaImageItem1.setRenderingMode(
- MediaItem.RENDERING_MODE_BLACK_BORDER - 11);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Media Item Invalid rendering Mode", flagForException);
-
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_CROPPING,
- mediaImageItem1.getRenderingMode());
- mediaImageItem1.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
- assertEquals("MediaVideo Item rendering Mode",
- MediaItem.RENDERING_MODE_STRETCH,
- mediaImageItem1.getRenderingMode());
- }
-
- /**
- * To Test the Media Image API : GetHeight and GetWidth
- */
- @LargeTest
- public void testMediaImageItemHeightWidth() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, imageItemRenderingMode, 5000);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- assertEquals("Image Height = Image Scaled Height",
- mediaImageItem1.getScaledHeight(), mediaImageItem1.getHeight());
- assertEquals("Image Width = Image Scaled Width",
- mediaImageItem1.getScaledWidth(), mediaImageItem1.getWidth());
- }
-
-
-
-/** This Test Case can be removed as this is already checked in TC 010 */
- /**
- * To Test the Media Image API : Scaled Height and Scaled GetWidth
- */
- @LargeTest
- public void testMediaImageItemScaledHeightWidth() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, imageItemRenderingMode, 5000);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- assertNotSame("Image Height = Image Scaled Height",
- mediaImageItem1.getScaledHeight(), mediaImageItem1.getHeight());
- assertNotSame("Image Width = Image Scaled Width",
- mediaImageItem1.getScaledWidth(), mediaImageItem1.getWidth());
- }
-
- /**
- * To Test the Media Image API : Get Effect, GetAllEffects, remove Effect
- */
-
- @LargeTest
- public void testMediaImageItemEffect() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- assertTrue("Effect List Size",
- (mediaImageItem1.getAllEffects().size() == 0) ? true : false);
- assertNull("Effect Item by ID", mediaImageItem1.getEffect("xyx"));
-
- final EffectColor effectColor =
- mVideoEditorHelper.createEffectItem(mediaImageItem1,
- "Effecton MVi1", 0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
- mediaImageItem1.addEffect(effectColor);
-
- assertTrue("Effect List Size",
- (mediaImageItem1.getAllEffects().size() == 1) ? true : false);
- assertEquals("Effect Item by Valid ID",
- effectColor, mediaImageItem1.getEffect(effectColor.getId()));
- assertNull("Effect Item by Invalid ID",
- mediaImageItem1.getEffect("xyz"));
- assertNull("Effect Item by Invalid ID",
- mediaImageItem1.removeEffect("effectId"));
- assertTrue("Effect List Size",
- (mediaImageItem1.getAllEffects().size() == 1) ? true : false);
- assertEquals("Effect Removed", effectColor,
- mediaImageItem1.removeEffect(effectColor.getId()));
- assertTrue("Effect List Size",
- (mediaImageItem1.getAllEffects().size() == 0) ? true : false);
- assertNull("Effect Item by ID", mediaImageItem1.getEffect("effectId"));
- }
-
- /**
- * To Test the Media Image API : Get Before and after transition
- */
-
- @LargeTest
- public void testMediaImageItemTransitions() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- assertNull("Begin Transition", mediaImageItem1.getBeginTransition());
- assertNull("End Transition", mediaImageItem1.getEndTransition());
-
- TransitionFadeBlack transition1 =
- mVideoEditorHelper.createTFadeBlack("transition1", mediaImageItem1,
- null, 0, Transition.BEHAVIOR_SPEED_UP);
- mVideoEditor.addTransition(transition1);
-
- assertEquals("Begin transition", transition1,
- mediaImageItem1.getEndTransition());
- assertNotNull("End Transition", mediaImageItem1.getEndTransition());
- assertTrue(mediaImageItem1.getEndTransition().getId().equals
- (transition1.getId()));
- assertTrue(mediaImageItem1.getEndTransition().getDuration() ==
- transition1.getDuration() ? true : false);
- assertTrue(mediaImageItem1.getEndTransition().getBehavior() ==
- transition1.getBehavior() ? true : false);
-
- TransitionFadeBlack transition2 = mVideoEditorHelper.createTFadeBlack(
- "transition2",null, mediaImageItem1, 0, Transition.BEHAVIOR_SPEED_UP);
- mVideoEditor.addTransition(transition2);
-
- assertNotNull("Begin transition", mediaImageItem1.getBeginTransition());
- assertEquals("End Transition", transition2,
- mediaImageItem1.getBeginTransition());
- assertTrue(mediaImageItem1.getBeginTransition().getId().equals(
- transition2.getId()));
- assertTrue(mediaImageItem1.getBeginTransition().getDuration() ==
- transition2.getDuration() ? true : false);
- assertTrue(mediaImageItem1.getBeginTransition().getBehavior() ==
- transition2.getBehavior() ? true : false);
- }
-
- /**
- * To Test the Media Image API : Get All Overlay, Get Overlay and remove
- * Overlay
- */
-
- @LargeTest
- public void testMediaImageItemOverlays() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String overlayItemFileName = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 12000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- assertTrue("Overlay List Size",
- (mediaImageItem1.getAllOverlays().size() == 0) ? true : false);
- assertNull("Overlay Item by ID", mediaImageItem1.getOverlay("xyz"));
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayItemFileName,
- 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId",
- mBitmap, 5000, 5000);
- mediaImageItem1.addOverlay(overlayFrame);
-
- assertTrue("Overlay List Size",
- (mediaImageItem1.getAllOverlays().size() == 1) ? true : false);
- assertEquals("Overlay Item by Valid ID", overlayFrame, mediaImageItem1
- .getOverlay(overlayFrame.getId()));
- assertNull("Overlay Item by Invalid ID",
- mediaImageItem1.getOverlay("xyz"));
- assertNull("Remove Overlay Item by Invalid ID",
- mediaImageItem1.removeOverlay("xyz"));
- assertTrue("Overlay List Size",
- (mediaImageItem1.getAllOverlays().size() == 1) ? true : false);
- assertEquals("Overlay Removed",
- overlayFrame, mediaImageItem1.removeOverlay(overlayFrame.getId()));
- assertTrue("Overlay List Size",
- (mediaImageItem1.getAllOverlays().size() == 0) ? true : false);
- assertNull("Overlay Item by ID",
- mediaImageItem1.getOverlay("effectId"));
- }
-
- /**
- * To test creation of Audio Track
- */
-
- @LargeTest
- public void testAudioTrack() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- assertEquals("Audio Track Item Duration", audioTrack.getDuration(),
- audioTrack.getTimelineDuration());
- assertEquals("Audio Track Start Time", 0, audioTrack.getStartTime());
- assertFalse("Audio Track is Looping", audioTrack.isLooping());
- audioTrack.getVolume();
- assertFalse("Audio Track Ducking is Disabled",
- audioTrack.isDuckingEnabled());
- assertTrue("Audio Track Filename",
- audioTrack.getFilename().equals(audioFileName));
- assertEquals("Audio Ducking Threshold", 0,
- audioTrack.getDuckingThreshhold());
- assertFalse("Audio Track Mute", audioTrack.isMuted());
- audioTrack.getDuckedTrackVolume();
- }
-
- /**
- * To test creation of Audio Track with set extract boundaries
- */
- @LargeTest
- public void testAudioTrackExtractBoundaries() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- audioTrack.setExtractBoundaries(1000, 5000);
- assertEquals("Audio Track Start time", 1000,
- audioTrack.getBoundaryBeginTime());
- assertEquals("Audio Track End time", 5000,
- audioTrack.getBoundaryEndTime());
- try {
- audioTrack.setExtractBoundaries(0, 100000000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Audio Track With endTime > FileDuration", flagForException);
- flagForException = false;
- try {
- audioTrack.setExtractBoundaries(100000000, 5000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Audio Track With startTime > FileDuration",
- flagForException);
- flagForException = false;
- try {
- audioTrack.setExtractBoundaries(0, 0);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- /* This is under discussion. Hence, checked for False */
- assertFalse("Audio Track With startTime = endTime", flagForException);
- assertEquals("Audio Track Start time", 0,
- audioTrack.getBoundaryBeginTime());
- assertEquals("Audio Track End time", 0,
- audioTrack.getBoundaryEndTime());
- assertEquals("Audio Track Start time",0,
- audioTrack.getBoundaryBeginTime());
- assertEquals("Audio Track End time", (audioTrack.getTimelineDuration()),
- audioTrack.getBoundaryEndTime());
- audioTrack.setExtractBoundaries(0, audioTrack.getDuration() / 2);
- assertEquals("Audio Track Start time",0,
- audioTrack.getBoundaryBeginTime());
- assertEquals("Audio Track End time", (audioTrack.getDuration() / 2),
- audioTrack.getBoundaryEndTime());
- audioTrack.setExtractBoundaries(1, audioTrack.getDuration() - 1);
- assertEquals("Audio Track Start time", 1,
- audioTrack.getBoundaryBeginTime());
- assertEquals("Audio Track End time", (audioTrack.getDuration() - 1),
- audioTrack.getBoundaryEndTime());
-
- flagForException = false;
- try {
- audioTrack.setExtractBoundaries(0, -1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue ("Audio Track end time < 0",flagForException);
- }
-
- /**
- * To test creation of Audio Track with set Start Time and Get Time
- */
- @LargeTest
- public void testAudioTrackSetGetTime() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
- /** set StartTime API is removed and start time is always 0 */
- assertEquals("Audio Track Start Time", 0, audioTrack.getStartTime());
- }
-
- /**
- * To Test the Audio Track API: Enable Ducking
- */
- @LargeTest
- public void testAudioTrackEnableDucking() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- assertFalse("Audio Ducking Disabled by default",
- audioTrack.isDuckingEnabled());
- audioTrack.enableDucking(45, 70);
- assertTrue("Audio Ducking Enabled", audioTrack.isDuckingEnabled());
- assertEquals("Audio Ducking Threshold", 45,
- audioTrack.getDuckingThreshhold());
- assertEquals("Audio Ducking Volume", 70,
- audioTrack.getDuckedTrackVolume());
- audioTrack.enableDucking(85, 70);
- assertEquals("Audio Ducking Threshold", 85,
- audioTrack.getDuckingThreshhold());
- assertEquals("Audio Ducking Volume", 70,
- audioTrack.getDuckedTrackVolume());
- try {
- audioTrack.enableDucking(91, 70);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Enable ducking threshold > 90", flagForException);
- flagForException = false;
- try {
- audioTrack.enableDucking(90, 101);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Enable ducking volume > 100", flagForException);
- flagForException = false;
- try {
- audioTrack.enableDucking(91, 101);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Enable ducking volume > 100 and threshold > 91",
- flagForException);
- flagForException = false;
- try {
- audioTrack.enableDucking(-1, 100);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Enable ducking threshold < 0", flagForException);
- flagForException = false;
- try {
- audioTrack.enableDucking(1, -1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Enable ducking lowVolume < 0", flagForException);
- flagForException = false;
- try {
- audioTrack.enableDucking(0, 50);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertFalse("Enable ducking threshold = 0", flagForException);
- }
-
- /**
- * To Test the Audio Track API: Looping
- */
- @LargeTest
- public void testAudioTrackLooping() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
- assertFalse("Audio Looping", audioTrack.isLooping());
- audioTrack.enableLoop();
- assertTrue("Audio Looping", audioTrack.isLooping());
- audioTrack.disableLoop();
- assertFalse("Audio Looping", audioTrack.isLooping());
- }
-
- /**
- * To Test the Audio Track API:Extract waveform data
- */
-
- @LargeTest
- public void testAudioTrackWaveFormData() throws Exception {
- /** Image item is added as dummy as Audio track cannot be added without
- * a media item in the story board
- */
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
-
- mVideoEditor.addAudioTrack(audioTrack);
- assertNull("WaveForm data", audioTrack.getWaveformData());
-
- final int[] progressUpdate = new int[105];
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- int i = 0;
- public void onProgress(Object item, int action, int progress) {
- progressUpdate[i++] = progress;
- }
- });
-
- final int[] progressWaveform = new int[105];
-
- audioTrack.extractAudioWaveform(
- new ExtractAudioWaveformProgressListener() {
- int i = 0;
- public void onProgress(int progress) {
- Log.i("AudioWaveformData","progress=" +progress);
- progressWaveform[i++] = progress;
- }
- });
- assertTrue("Progress of WaveForm data", mVideoEditorHelper
- .checkProgressCBValues(progressWaveform));
- assertNotNull("WaveForm data", audioTrack.getWaveformData());
- assertTrue("WaveForm Frame Duration",
- (audioTrack.getWaveformData().getFrameDuration() > 0 ?
- true : false));
- assertTrue("WaveForm Frame Count",
- (audioTrack.getWaveformData().getFramesCount() > 0 ? true : false));
- assertTrue("WaveForm Gain",
- (audioTrack.getWaveformData().getFrameGains().length > 0 ?
- true : false));
- }
-
- /**
- * To Test the Audio Track API: Mute
- */
- @LargeTest
- public void testAudioTrackMute() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- assertFalse("Audio Track UnMute", audioTrack.isMuted());
- audioTrack.setMute(true);
- assertTrue("Audio Track Mute", audioTrack.isMuted());
- audioTrack.setMute(false);
- assertFalse("Audio Track UnMute", audioTrack.isMuted());
- }
-
- /**
- * To Test the Audio Track API: Get Volume and Set Volume
- */
- @LargeTest
- public void testAudioTrackGetSetVolume() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- audioTrack.setVolume(0);
- assertEquals("Audio Volume", 0, audioTrack.getVolume());
- assertFalse("Audio Track UnMute", audioTrack.isMuted());
- audioTrack.setVolume(45);
- assertEquals("Audio Volume", 45, audioTrack.getVolume());
- assertFalse("Audio Track UnMute", audioTrack.isMuted());
- try {
- audioTrack.setVolume(-1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Volume = -1", flagForException);
- assertEquals("Audio Volume", 45, audioTrack.getVolume());
- flagForException = false;
- try {
- audioTrack.setVolume(101);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Volume = 101", flagForException);
- flagForException = false;
- try {
- audioTrack.setVolume(1000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Volume = 10000", flagForException);
- assertEquals("Audio Volume", 45, audioTrack.getVolume());
- }
-
- /**
- * To test Effect Color.
- */
- @LargeTest
- public void testAllEffects() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect1", 1000, 1000, EffectColor.TYPE_COLOR,
- EffectColor.PINK);
- mediaVideoItem1.addEffect(effectColor1);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor1.getMediaItem());
- assertTrue("Effect Id", effectColor1.getId().equals("effect1"));
- assertEquals("Effect StartTime", 1000, effectColor1.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor1.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_COLOR,
- effectColor1.getType());
- assertEquals("Effect Color", EffectColor.PINK, effectColor1.getColor());
-
- final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect2", 2000, 1000, EffectColor.TYPE_COLOR,
- EffectColor.GRAY);
- mediaVideoItem1.addEffect(effectColor2);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor2.getMediaItem());
- assertTrue("Effect Id", effectColor2.getId().equals("effect2"));
- assertEquals("Effect StartTime", 2000, effectColor2.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor2.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_COLOR,
- effectColor2.getType());
- assertEquals("Effect Color", EffectColor.GRAY, effectColor2.getColor());
-
- final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect3", 3000, 1000, EffectColor.TYPE_COLOR,
- EffectColor.GREEN);
- mediaVideoItem1.addEffect(effectColor3);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor3.getMediaItem());
- assertTrue("Effect Id", effectColor3.getId().equals("effect3"));
- assertEquals("Effect StartTime", 3000, effectColor3.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor3.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_COLOR,
- effectColor3.getType());
- assertEquals("Effect Color", EffectColor.GREEN, effectColor3.getColor());
-
- final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect4", 4000, 1000, EffectColor.TYPE_GRADIENT,
- EffectColor.PINK);
- mediaVideoItem1.addEffect(effectColor4);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor4.getMediaItem());
- assertTrue("Effect Id", effectColor4.getId().equals("effect4"));
- assertEquals("Effect StartTime", 4000, effectColor4.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor4.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_GRADIENT,
- effectColor4.getType());
- assertEquals("Effect Color", EffectColor.PINK, effectColor4.getColor());
-
- final EffectColor effectColor5 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect5", 5000, 1000,
- EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
- mediaVideoItem1.addEffect(effectColor5);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor5.getMediaItem());
- assertTrue("Effect Id", effectColor5.getId().equals("effect5"));
- assertEquals("Effect StartTime", 5000, effectColor5.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor5.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_GRADIENT,
- effectColor5.getType());
- assertEquals("Effect Color", EffectColor.GRAY, effectColor5.getColor());
-
- final EffectColor effectColor6 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect6", 6000, 1000,
- EffectColor.TYPE_GRADIENT, EffectColor.GREEN);
- mediaVideoItem1.addEffect(effectColor6);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor6.getMediaItem());
- assertTrue("Effect Id", effectColor6.getId().equals("effect6"));
- assertEquals("Effect StartTime", 6000, effectColor6.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor6.getDuration());
- assertEquals("Effect Type",
- EffectColor.TYPE_GRADIENT, effectColor6.getType());
- assertEquals("Effect Color",
- EffectColor.GREEN, effectColor6.getColor());
-
- final EffectColor effectColor7 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect7", 7000, 1000,
- EffectColor.TYPE_FIFTIES, 0);
- mediaVideoItem1.addEffect(effectColor7);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor7.getMediaItem());
- assertTrue("Effect Id", effectColor7.getId().equals("effect7"));
- assertEquals("Effect StartTime", 7000, effectColor7.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor7.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_FIFTIES,
- effectColor7.getType());
- assertEquals("Effect Color", -1, effectColor7.getColor());
-
- final EffectColor effectColor8 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect8", 8000, 1000, EffectColor.TYPE_SEPIA, 0);
- mediaVideoItem1.addEffect(effectColor8);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor8.getMediaItem());
- assertTrue("Effect Id", effectColor8.getId().equals("effect8"));
- assertEquals("Effect StartTime", 8000, effectColor8.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor8.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_SEPIA,
- effectColor8.getType());
- assertEquals("Effect Color", -1, effectColor8.getColor());
-
- final EffectColor effectColor9 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect9", 9000, 1000,
- EffectColor.TYPE_NEGATIVE, 0);
- mediaVideoItem1.addEffect(effectColor9);
-
- assertEquals("Associated Media Item", mediaVideoItem1,
- effectColor9.getMediaItem());
- assertTrue("Effect Id", effectColor9.getId().equals("effect9"));
- assertEquals("Effect StartTime", 9000, effectColor9.getStartTime());
- assertEquals("Effect EndTime", 1000, effectColor9.getDuration());
- assertEquals("Effect Type", EffectColor.TYPE_NEGATIVE,
- effectColor9.getType());
- assertEquals("Effect Color", -1, effectColor9.getColor());
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect9",
- 9000, 1000, EffectColor.TYPE_COLOR - 1, 0);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect type Invalid", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect9",
- 9000, 1000, EffectColor.TYPE_FIFTIES + 1, 0);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect type Invalid", flagForException);
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect10",
- 10000, 1000, EffectColor.TYPE_FIFTIES +
- EffectColor.TYPE_GRADIENT, 0);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect type Invalid", flagForException);
- }
-
- /**
- * To test Effect Color : Set duration and Get Duration
- */
- @LargeTest
- public void testEffectSetgetDuration() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
- mediaVideoItem1, "effect1", 1000, 2000,
- EffectColor.TYPE_COLOR, EffectColor.PINK);
- mediaVideoItem1.addEffect(effectColor1);
-
- effectColor1.setDuration(5000);
- assertEquals("Updated Effect Duration", 5000,
- effectColor1.getDuration());
- try {
- effectColor1.setDuration(mediaVideoItem1.getDuration() + 1000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect Color duration > mediaVideoItemDuration",
- flagForException);
- assertEquals("Effect Duration", 5000, effectColor1.getDuration());
- flagForException = false;
- try {
- effectColor1.setDuration(-1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect Color duration = -1", flagForException);
- }
-
- /**
- * To test Effect Color : UNDEFINED color param value
- */
- @LargeTest
- public void testEffectUndefinedColorParam() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- try{
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1", 1000,
- 2000, EffectColor.TYPE_COLOR, 0xabcdabcd);
- }catch (IllegalArgumentException e){
- flagForException = true;
- }
- assertTrue("Invalid Effect added",flagForException);
- }
-
- /**
- * To test Effect Color : with Invalid StartTime and Duration
- */
- @LargeTest
- public void testEffectInvalidStartTimeAndDuration() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp";
- final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName, videoItemRenderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1",
- 400000000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect with invalid StartTime", flagForException);
-
- flagForException = false;
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1", -1,
- 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect with invalid StartTime", flagForException);
-
- flagForException = false;
- try {
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1",
- 2000, -1, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect with invalid Duration", flagForException);
- }
-
-
- /** Test cases 29, 30, 31, 32 and 33 are removed */
-
-
- /**
- * To test Effect : with NULL Media Item
- */
- @LargeTest
- public void testEffectNullMediaItem() throws Exception {
- boolean flagForException = false;
- try {
- mVideoEditorHelper.createEffectItem(null, "effect1", 1000, 4000,
- EffectColor.TYPE_COLOR, EffectColor.GREEN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Effect with null MediaItem", flagForException);
- }
-
- /**
- * To test Effect : KenBurn Effect
- */
- @LargeTest
- public void testEffectKenBurn() throws Exception {
- // Test ken burn effect using a JPEG file.
- testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg",
- "mediaImageItem1");
-
- // Test ken burn effect using a PNG file
- testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png",
- "mediaImageItem2");
- }
-
- private void testEffectKenBurn(final String imageItemFileName,
- final String MediaId) throws Exception {
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, MediaId,
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
- (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
- (mediaImageItem.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
- mediaImageItem.getHeight());
-
- final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
- mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
-
- assertNotNull("EffectKenBurns: " + imageItemFileName,
- kbEffectOnMediaItem);
-
- mediaImageItem.addEffect(kbEffectOnMediaItem);
- assertEquals("KenBurn Start Rect: " + imageItemFileName, startRect,
- kbEffectOnMediaItem.getStartRect());
-
- assertEquals("KenBurn End Rect: " + imageItemFileName, endRect,
- kbEffectOnMediaItem.getEndRect());
- }
-
- /**
- * To test KenBurnEffect : Set StartRect and EndRect
- */
-
- @LargeTest
- public void testEffectKenBurnSet() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
- (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
- (mediaImageItem.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
- mediaImageItem.getHeight());
-
- EffectKenBurns kbEffectOnMediaItem=null;
- kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2",
- startRect, endRect, 500, 3000);
-
- assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
- mediaImageItem.addEffect(kbEffectOnMediaItem);
- assertEquals("KenBurn Start Rect", startRect,
- kbEffectOnMediaItem.getStartRect());
- assertEquals("KenBurn End Rect", endRect,
- kbEffectOnMediaItem.getEndRect());
-
- final Rect startRect1 = new Rect((mediaImageItem.getHeight() / 5),
- (mediaImageItem.getWidth() / 5), (mediaImageItem.getHeight() / 4),
- (mediaImageItem.getWidth() / 4));
- final Rect endRect1 = new Rect(10, 10, mediaImageItem.getWidth() / 4,
- mediaImageItem.getHeight() / 4);
-
- /* Added newly to take care of removal set APIs */
- kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_changed",
- startRect1, endRect1, 500, 3000);
-
- assertEquals("KenBurn Start Rect", startRect1,
- kbEffectOnMediaItem.getStartRect());
- assertEquals("KenBurn End Rect", endRect1,
- kbEffectOnMediaItem.getEndRect());
-
- final Rect zeroRect = new Rect(0, 0, 0, 0);
- try {
- kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroStart",
- zeroRect, endRect, 500, 3000);
-
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid Start Rect", flagForException);
-
- flagForException = false;
- try {
- kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroEnd",
- startRect, zeroRect, 500, 3000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid End Rect", flagForException);
- }
-
- /**
- * To test Transition : Fade To Black with all behavior
- * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
- */
-
- @LargeTest
- public void testTransitionFadeBlack() throws Exception {
-
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String videoItemFilename2 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename3 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final String videoItemFilename4 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFilename5 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
- boolean flagForException = false;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionFadeBlack transition1And2 = mVideoEditorHelper
- .createTFadeBlack("transition1And2", mediaVideoItem1,
- mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP);
- mVideoEditor.addTransition(transition1And2);
-
- assertTrue("Transition ID",
- transition1And2.getId().equals("transition1And2"));
- assertEquals("Transtion After Media item",
- mediaVideoItem1, transition1And2.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem2,
- transition1And2.getBeforeMediaItem());
- assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
- transition1And2.getBehavior());
-
- final MediaImageItem mediaImageItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem3);
-
- final TransitionFadeBlack transition2And3 =
- mVideoEditorHelper.createTFadeBlack("transition2And3", mediaVideoItem2,
- mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN);
- mVideoEditor.addTransition(transition2And3);
-
- assertTrue("Transition ID",
- transition2And3.getId().equals("transition2And3"));
- assertEquals("Transtion After Media item", mediaVideoItem2,
- transition2And3.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaImageItem3,
- transition2And3.getBeforeMediaItem());
- assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
- transition2And3.getBehavior());
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final TransitionFadeBlack transition3And4 =
- mVideoEditorHelper.createTFadeBlack("transition3And4", mediaImageItem3,
- mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR);
- mVideoEditor.addTransition(transition3And4);
-
- assertTrue("Transition ID",
- transition3And4.getId().equals("transition3And4"));
- assertEquals("Transtion After Media item", mediaImageItem3,
- transition3And4.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem4,
- transition3And4.getBeforeMediaItem());
- assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
- transition3And4.getBehavior());
-
- final MediaVideoItem mediaVideoItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem5);
-
- final TransitionFadeBlack transition4And5 =
- mVideoEditorHelper.createTFadeBlack("transition4And5", mediaVideoItem4,
- mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition4And5);
-
- assertTrue("Transition ID",
- transition4And5.getId().equals("transition4And5"));
- assertEquals("Transtion After Media item", mediaVideoItem4,
- transition4And5.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem5,
- transition4And5.getBeforeMediaItem());
- assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
- transition4And5.getBehavior());
-
- final MediaVideoItem mediaVideoItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem6.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem6);
-
- final TransitionFadeBlack transition5And6 =
- mVideoEditorHelper.createTFadeBlack("transition5And6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW);
- mVideoEditor.addTransition(transition5And6);
-
- assertTrue("Transition ID",
- transition5And6.getId().equals("transition5And6"));
- assertEquals("Transtion After Media item", mediaVideoItem5,
- transition5And6.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem6,
- transition5And6.getBeforeMediaItem());
- assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
- transition5And6.getBehavior());
- flagForException = false;
- try {
- mVideoEditorHelper.createTFadeBlack("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTFadeBlack("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- }
-
- /**
- * To test Transition : CrossFade with all behavior
- * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
- */
-
- @LargeTest
- public void testTransitionCrossFade() throws Exception {
-
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String videoItemFilename2 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename3 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final String videoItemFilename4 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFilename5 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionCrossfade transition1And2 =
- mVideoEditorHelper.createTCrossFade("transition1And2", mediaVideoItem1,
- mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP);
- mVideoEditor.addTransition(transition1And2);
-
- assertTrue("Transition ID",
- transition1And2.getId().equals("transition1And2"));
- assertEquals("Transtion After Media item", mediaVideoItem1,
- transition1And2.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem2,
- transition1And2.getBeforeMediaItem());
- assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
- transition1And2.getBehavior());
-
- final MediaImageItem mediaImageItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem3);
-
- final TransitionCrossfade transition2And3 =
- mVideoEditorHelper.createTCrossFade("transition2And3", mediaVideoItem2,
- mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN);
- mVideoEditor.addTransition(transition2And3);
-
- assertTrue("Transition ID",
- transition2And3.getId().equals("transition2And3"));
- assertEquals("Transtion After Media item", mediaVideoItem2,
- transition2And3.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaImageItem3,
- transition2And3.getBeforeMediaItem());
- assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
- transition2And3.getBehavior());
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(0, 18000);
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final TransitionCrossfade transition3And4 =
- mVideoEditorHelper.createTCrossFade("transition3And4", mediaImageItem3,
- mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR);
- mVideoEditor.addTransition(transition3And4);
-
- assertTrue("Transition ID",
- transition3And4.getId().equals("transition3And4"));
- assertEquals("Transtion After Media item", mediaImageItem3,
- transition3And4.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem4,
- transition3And4.getBeforeMediaItem());
- assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
- transition3And4.getBehavior());
-
- final MediaVideoItem mediaVideoItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem5);
-
- final TransitionCrossfade transition4And5 =
- mVideoEditorHelper.createTCrossFade("transition4And5", mediaVideoItem4,
- mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition4And5);
-
- assertTrue("Transition ID",
- transition4And5.getId().equals("transition4And5"));
- assertEquals("Transtion After Media item", mediaVideoItem4,
- transition4And5.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem5,
- transition4And5.getBeforeMediaItem());
- assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
- transition4And5.getBehavior());
-
- final MediaVideoItem mediaVideoItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem6.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem6);
-
- final TransitionCrossfade transition5And6 =
- mVideoEditorHelper.createTCrossFade("transition5And6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW);
- mVideoEditor.addTransition(transition5And6);
-
- assertTrue("Transition ID",
- transition5And6.getId().equals("transition5And6"));
- assertEquals("Transtion After Media item", mediaVideoItem5,
- transition5And6.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem6,
- transition5And6.getBeforeMediaItem());
- assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
- transition5And6.getBehavior());
-
- flagForException = false;
- try {
- mVideoEditorHelper.createTCrossFade("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTCrossFade("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- }
-
- /**
- * To test Transition : Sliding with all behavior
- * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST and Direction =
- * DIRECTION_RIGHT_OUT_LEFT_IN
- * ,DIRECTION_LEFT_OUT_RIGHT_IN,DIRECTION_TOP_OUT_BOTTOM_IN
- * ,DIRECTION_BOTTOM_OUT_TOP_IN
- */
-
- @LargeTest
- public void testTransitionSliding() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String videoItemFilename2 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String videoItemFilename3 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final String videoItemFilename4 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFilename5 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
- boolean flagForException = false;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionSliding transition1And2 =
- mVideoEditorHelper.createTSliding("transition1And2", mediaVideoItem1,
- mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- mVideoEditor.addTransition(transition1And2);
-
- assertTrue("Transition ID",
- transition1And2.getId().equals("transition1And2"));
- assertEquals("Transtion After Media item", mediaVideoItem1,
- transition1And2.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem2,
- transition1And2.getBeforeMediaItem());
- assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
- transition1And2.getBehavior());
- assertEquals("Transition Sliding",
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN,
- transition1And2.getDirection());
-
- final MediaImageItem mediaImageItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem3);
-
- final TransitionSliding transition2And3 =
- mVideoEditorHelper.createTSliding("transition2And3",
- mediaVideoItem2, mediaImageItem3, 1000,
- Transition.BEHAVIOR_SPEED_DOWN,
- TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
- mVideoEditor.addTransition(transition2And3);
-
- assertTrue("Transition ID",
- transition2And3.getId().equals("transition2And3"));
- assertEquals("Transtion After Media item", mediaVideoItem2,
- transition2And3.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaImageItem3,
- transition2And3.getBeforeMediaItem());
- assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
- transition2And3.getBehavior());
- assertEquals("Transition Sliding",
- TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN,
- transition2And3.getDirection());
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(0, 18000);
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final TransitionSliding transition3And4 =
- mVideoEditorHelper.createTSliding("transition3And4", mediaImageItem3,
- mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR,
- TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN);
- mVideoEditor.addTransition(transition3And4);
-
- assertTrue("Transition ID",
- transition3And4.getId().equals("transition3And4"));
- assertEquals("Transtion After Media item", mediaImageItem3,
- transition3And4.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem4,
- transition3And4.getBeforeMediaItem());
- assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
- transition3And4.getBehavior());
- assertEquals("Transition Sliding",
- TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN,
- transition3And4.getDirection());
-
- final MediaVideoItem mediaVideoItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem5);
-
- final TransitionSliding transition4And5 =
- mVideoEditorHelper.createTSliding("transition4And5", mediaVideoItem4,
- mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN);
- mVideoEditor.addTransition(transition4And5);
-
- assertTrue("Transition ID",
- transition4And5.getId().equals("transition4And5"));
- assertEquals("Transtion After Media item", mediaVideoItem4,
- transition4And5.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem5,
- transition4And5.getBeforeMediaItem());
- assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
- transition4And5.getBehavior());
- assertEquals("Transition Sliding",
- TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN,
- transition4And5.getDirection());
-
- final MediaVideoItem mediaVideoItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem6.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem6);
-
- final TransitionSliding transition5And6 =
- mVideoEditorHelper.createTSliding("transition5And6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- mVideoEditor.addTransition(transition5And6);
-
- assertTrue("Transition ID",
- transition5And6.getId().equals("transition5And6"));
- assertEquals("Transtion After Media item", mediaVideoItem5,
- transition5And6.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem6,
- transition5And6.getBeforeMediaItem());
- assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
- transition5And6.getBehavior());
- assertEquals("Transition Sliding",
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN,
- transition5And6.getDirection());
-
- flagForException = false;
- try {
- mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN - 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition Sliding with Invalid Direction", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
- TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN + 1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition Sliding with Invalid behavior", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition Sliding with Invalid behavior", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition Sliding with Invalid behavior", flagForException);
- }
-
- /**
- * To test Transition : Alpha with all behavior
- * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
- */
-
- @LargeTest
- public void testTransitionAlpha() throws Exception {
-
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String videoItemFilename2 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String videoItemFilename3 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final String videoItemFilename4 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFilename5 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
- final String maskFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionAlpha transition1And2 =
- mVideoEditorHelper.createTAlpha("transition1And2", mediaVideoItem1,
- mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP, maskFilename,
- 10, false);
- mVideoEditor.addTransition(transition1And2);
-
- assertTrue("Transition ID",
- transition1And2.getId().equals("transition1And2"));
- assertEquals("Transtion After Media item", mediaVideoItem1,
- transition1And2.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem2,
- transition1And2.getBeforeMediaItem());
- assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
- transition1And2.getBehavior());
- assertTrue("Transition maskFile",
- transition1And2.getMaskFilename().equals(maskFilename));
- assertEquals("Transition BlendingPercent", 10,
- transition1And2.getBlendingPercent());
- assertFalse("Transition Invert", transition1And2.isInvert());
-
- final MediaImageItem mediaImageItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem3);
-
- final TransitionAlpha transition2And3 =
- mVideoEditorHelper.createTAlpha("transition2And3", mediaVideoItem2,
- mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN,
- maskFilename, 30, false);
- mVideoEditor.addTransition(transition2And3);
-
- assertTrue("Transition ID",
- transition2And3.getId().equals("transition2And3"));
- assertEquals("Transtion After Media item", mediaVideoItem2,
- transition2And3.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaImageItem3,
- transition2And3.getBeforeMediaItem());
- assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
- transition2And3.getBehavior());
- assertTrue("Transition maskFile",
- transition2And3.getMaskFilename().equals(maskFilename));
- assertEquals("Transition BlendingPercent", 30,
- transition2And3.getBlendingPercent());
- assertFalse("Transition Invert", transition2And3.isInvert());
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(0, 18000);
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final TransitionAlpha transition3And4 =
- mVideoEditorHelper.createTAlpha("transition3And4", mediaImageItem3,
- mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR, maskFilename,
- 50, false);
- mVideoEditor.addTransition(transition3And4);
-
- assertTrue("Transition ID",
- transition3And4.getId().equals("transition3And4"));
- assertEquals("Transtion After Media item", mediaImageItem3,
- transition3And4.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem4,
- transition3And4.getBeforeMediaItem());
- assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
- transition3And4.getBehavior());
- assertTrue("Transition maskFile",
- transition3And4.getMaskFilename().equals(maskFilename));
- assertEquals("Transition BlendingPercent", 50,
- transition3And4.getBlendingPercent());
- assertFalse("Transition Invert", transition3And4.isInvert());
-
- final MediaVideoItem mediaVideoItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem5);
-
- final TransitionAlpha transition4And5 =
- mVideoEditorHelper.createTAlpha("transition4And5", mediaVideoItem4,
- mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST,
- maskFilename, 70, true);
- mVideoEditor.addTransition(transition4And5);
-
- assertTrue("Transition ID",
- transition4And5.getId().equals("transition4And5"));
- assertEquals("Transtion After Media item", mediaVideoItem4,
- transition4And5.getAfterMediaItem());
- assertEquals("Transtion Before Media item", mediaVideoItem5,
- transition4And5.getBeforeMediaItem());
- assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
- assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
- transition4And5.getBehavior());
- assertTrue("Transition maskFile",
- transition4And5.getMaskFilename().equals(maskFilename));
- assertEquals("Transition BlendingPercent", 70,
- transition4And5.getBlendingPercent());
- assertTrue("Transition Invert", transition4And5.isInvert());
-
- final MediaVideoItem mediaVideoItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem6.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem6);
-
- try {
- mVideoEditorHelper.createTAlpha("transition5And6", mediaVideoItem5,
- mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
- INPUT_FILE_PATH + "imDummyFile.jpg", 70,
- true);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("MaskFile is not exsisting", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTAlpha("transition5And6", null, null, 2000,
- Transition.BEHAVIOR_MIDDLE_SLOW, maskFilename, 101, true);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Invalid Blending Percent", flagForException);
-
- flagForException = false;
- try {
- mVideoEditorHelper.createTAlpha("transitiond6", mediaVideoItem4,
- mediaVideoItem5, 2000, Transition.BEHAVIOR_SPEED_UP - 1,
- maskFilename, 30, false);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- flagForException = false;
- try {
- mVideoEditorHelper.createTAlpha("transitiond6", mediaVideoItem4,
- mediaVideoItem5, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
- maskFilename, 30, false);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
- }
-
- /**
- * To test Frame Overlay for Media Video Item
- */
-
- @LargeTest
- public void testFrameOverlayVideoItem() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_256kbps_0_25.3gp";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_176x144_Overlay1.png";
- final String overlayFile2 = INPUT_FILE_PATH + "IMG_176x144_Overlay2.png";
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final Bitmap mBitmap1 = mVideoEditorHelper.getBitmap(overlayFile1,
- 176, 144);
- final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
- mediaVideoItem1, "overlayId1", mBitmap1, 5000, 5000);
- mediaVideoItem1.addOverlay(overlayFrame1);
-
- assertEquals("Overlay : Media Item", mediaVideoItem1,
- overlayFrame1.getMediaItem());
- assertTrue("Overlay Id", overlayFrame1.getId().equals("overlayId1"));
- assertEquals("Overlay Bitmap", mBitmap1, overlayFrame1.getBitmap());
- assertEquals("Overlay Start Time", 5000, overlayFrame1.getStartTime());
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
- Bitmap upddateBmp = mVideoEditorHelper.getBitmap(overlayFile2, 176, 144);
- overlayFrame1.setBitmap(upddateBmp);
- assertEquals("Overlay Update Bitmap", upddateBmp, overlayFrame1.getBitmap());
- upddateBmp.recycle();
- }
-
- /**
- * To test Frame Overlay for Media Video Item : Set duration and Get
- * Duration
- */
-
- @LargeTest
- public void testFrameOverlaySetAndGet() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
- mediaVideoItem1, "overlayId1", mBitmap, 5000, 5000);
- mediaVideoItem1.addOverlay(overlayFrame1);
- overlayFrame1.setDuration(5000);
-
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
- try {
- overlayFrame1.setDuration(mediaVideoItem1.getDuration() + 10000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay Duration > MediaVideo Item Duration",
- flagForException);
-
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
- flagForException = false;
-
- try {
- overlayFrame1.setDuration(-1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay Duration = -1", flagForException);
- }
-
- /**
- * To test Frame Overlay for Media Video Item : Set duration and Get
- * Duration
- */
-
- @LargeTest
- public void testFrameOverlayInvalidTime() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId1",
- mBitmap, 400000000, 2000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
-
- flagForException = false;
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId2",
- mBitmap, -1, 2000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
-
- flagForException = false;
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId3",
- mBitmap, 2000, -1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
- }
-
- /**
- * To test Frame Overlay for Media Image Item
- */
- @LargeTest
- public void testFrameOverlayImageItem() throws Exception {
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- final String overlayFile2 = INPUT_FILE_PATH + "IMG_640x480_Overlay2.png";
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- imageItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1, 640,
- 480);
- final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
- mediaImageItem1, "overlayId1", mBitmap, 5000, 5000);
- mediaImageItem1.addOverlay(overlayFrame1);
-
- assertEquals("Overlay : Media Item", mediaImageItem1,
- overlayFrame1.getMediaItem());
- assertTrue("Overlay Id", overlayFrame1.getId().equals("overlayId1"));
- assertEquals("Overlay Bitmap",mBitmap ,overlayFrame1.getBitmap());
- assertEquals("Overlay Start Time", 5000, overlayFrame1.getStartTime());
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
- Bitmap upddateBmp = mVideoEditorHelper.getBitmap(overlayFile2, 640, 480);
-
- overlayFrame1.setBitmap(upddateBmp);
- assertEquals("Overlay Update Bitmap", upddateBmp, overlayFrame1.getBitmap());
- upddateBmp.recycle();
- }
-
- /**
- * To test Frame Overlay for Media Image Item : Set duration and Get
- * Duration
- */
-
- @LargeTest
- public void testFrameOverlaySetAndGetImage() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
- mediaImageItem1, "overlayId1", mBitmap, 5000, 5000);
- mediaImageItem1.addOverlay(overlayFrame1);
-
- overlayFrame1.setDuration(5000);
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
- try {
- overlayFrame1.setDuration(mediaImageItem1.getDuration() + 10000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay Duration > Media Item Duration", flagForException);
- assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
- flagForException = false;
- try {
- overlayFrame1.setDuration(-1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay Duration = -1", flagForException);
- }
-
- /**
- * To test Frame Overlay for Media Image Item :Invalid StartTime and
- * Duration
- */
-
- @LargeTest
- public void testFrameOverlayInvalidTimeImage() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId1",
- mBitmap, 400000000, 2000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
-
- flagForException = false;
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId2",
- mBitmap, -1, 2000);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
-
- flagForException = false;
- try {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1,
- 640, 480);
- mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId3",
- mBitmap, 2000, -1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Overlay With Invalid Start Time", flagForException);
- }
-
- /**
- * To Test Frame Overlay Media Image Item :JPG File
- */
-
- @LargeTest
- public void testFrameOverlayJPGImage() throws Exception {
-
- final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- imageItemFilename, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile1, 640,
- 480);
- mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId1",
- mBitmap, 5000, 5000);
- }
-
- /**
- * To test Video Editor API
- *
- * @throws Exception
- */
- @LargeTest
- public void testVideoEditorAPI() throws Exception {
-
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String videoItemFileName3 = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
- final String audioFilename1 = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- final String audioFilename2 = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- TransitionCrossfade transition2And4;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName1, renderingMode);
- mediaVideoItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFileName2, renderingMode);
- mediaVideoItem2.setExtractBoundaries(mediaVideoItem2.getDuration() / 4,
- mediaVideoItem2.getDuration() / 2);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFileName3, renderingMode);
- mediaVideoItem3.setExtractBoundaries(mediaVideoItem3.getDuration() / 2,
- mediaVideoItem3.getDuration());
- mVideoEditor.addMediaItem(mediaVideoItem3);
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- imageItemFileName1, 5000, renderingMode);
-
- final MediaImageItem mediaImageItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- imageItemFileName2, 5000, renderingMode);
-
- List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 3, mediaList.size());
-
- mVideoEditor.insertMediaItem(mediaImageItem1, mediaVideoItem2.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 4, mediaList.size());
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
- assertEquals("Media item 4", mediaImageItem1, mediaList.get(2));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(3));
-
- mVideoEditor.insertMediaItem(mediaImageItem2, mediaImageItem1.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 5, mediaList.size());
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
- assertEquals("Media item 4", mediaImageItem1, mediaList.get(2));
- assertEquals("Media item 5", mediaImageItem2, mediaList.get(3));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
- mVideoEditor.moveMediaItem(mediaVideoItem1.getId(), mediaImageItem2.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 5, mediaList.size());
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(0));
- assertEquals("Media item 4", mediaImageItem1, mediaList.get(1));
- assertEquals("Media item 5", mediaImageItem2, mediaList.get(2));
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(3));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
- assertEquals("Media Item 1", mediaVideoItem1,
- mVideoEditor.getMediaItem(mediaVideoItem1.getId()));
-
- flagForException = false;
- transition2And4 = null;
- try{
- transition2And4 = mVideoEditorHelper.createTCrossFade(
- "transition2And4", mediaVideoItem2, mediaImageItem1, 2000,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition2And4);
- }
- catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertFalse("Transition2and4 cannot be created", flagForException);
-
-
- TransitionCrossfade transition1And3 = null;
- flagForException = false;
- try{
- transition1And3 = mVideoEditorHelper.createTCrossFade(
- "transition1And3", mediaVideoItem1, mediaVideoItem2, 5000,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition1And3);
- }catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Transition1and3 cannot be created", flagForException);
-
- List<Transition> transitionList = mVideoEditor.getAllTransitions();
- assertEquals("Transition List", 1, transitionList.size());
-
- assertEquals("Transition 2", transition2And4,
- mVideoEditor.getTransition(transition2And4.getId()));
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFilename1);
- mVideoEditor.addAudioTrack(audioTrack);
-
- List<AudioTrack> audioList = mVideoEditor.getAllAudioTracks();
- assertEquals("Audio List", 1, audioList.size());
-
- final AudioTrack audioTrack1 = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack1", audioFilename2);
- flagForException = false;
- try {
- mVideoEditor.addAudioTrack(audioTrack1);
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Audio Track support is 1 ", flagForException);
-
- flagForException = false;
- try {
- mVideoEditor.insertAudioTrack(audioTrack1,"audioTrack");
- } catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Audio Track supports is 1 ", flagForException);
-
- assertEquals("Removing AudioTrack", audioTrack,
- mVideoEditor.removeAudioTrack(audioTrack.getId()));
-
- assertEquals("Removing transition", transition2And4,
- mVideoEditor.removeTransition(transition2And4.getId()));
-
- assertEquals("Removing Media Item", mediaVideoItem2,
- mVideoEditor.removeMediaItem(mediaVideoItem2.getId()));
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_16_9);
- assertEquals("Check Aspect Ratio", MediaProperties.ASPECT_RATIO_16_9,
- mVideoEditor.getAspectRatio());
-
- long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
- + mediaVideoItem3.getTimelineDuration()
- + mediaImageItem1.getDuration()
- + mediaImageItem2.getDuration();
- assertEquals("Story Board Duration", storyBoardDuration,
- mVideoEditor.getDuration());
- }
-
- /**
- * To add Audio Track Greater than MediaItem Duration
- *
- * @throws Exception
- */
- @LargeTest
- public void testVideoLessThanAudio() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String audioTrackFilename = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrackId", audioTrackFilename);
- mVideoEditor.addAudioTrack(audioTrack);
- assertEquals("Storyboard = mediaItem Duration",
- mediaVideoItem1.getDuration(), mVideoEditor.getDuration());
- assertTrue("Audio Duration > mediaItem Duration",
- (audioTrack.getDuration() > mediaVideoItem1.getDuration() ?
- true : false));
- }
-
- /**
- * To test Video Editor API with 1080 P
- *
- * @throws Exception
- */
- @LargeTest
- public void testVideoContentHD() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "H264_BP_1920x1080_30fps_1200Kbps_1_10.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final MediaVideoItem mediaVideoItem1;
- // 1080p resolution is supported on some devices
- // but not on other devices.
- // So this test case is not generic and
- // hence we always assert true
- boolean flagForException = true;
- try {
- mediaVideoItem1 = mVideoEditorHelper.createMediaItem(mVideoEditor,
- "m1", videoItemFileName1, renderingMode);
- } catch (IllegalArgumentException e) {
- }
- assertTrue("VideoContent 1920x1080", flagForException);
- }
-
-
- /**
- * To test: Remove audio track
- *
- * @throws Exception
- */
- @LargeTest
- public void testRemoveAudioTrack() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack1", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- assertEquals("Audio Track Item Duration", audioTrack.getDuration(),
- audioTrack.getTimelineDuration());
- assertTrue("Audio Track ID", audioTrack.getId().equals("audioTrack1"));
- assertNotNull("Remove Audio Track",
- mVideoEditor.removeAudioTrack("audioTrack1"));
- try{
- mVideoEditor.removeAudioTrack("audioTrack1");
- }catch (IllegalArgumentException e){
- flagForException = true;
- }
- assertTrue("Remove Audio Track not possible", flagForException);
- }
-
- /**
- * To test: Disable ducking
- *
- * @throws Exception
- */
- @LargeTest
- public void testAudioDuckingDisable() throws Exception {
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- audioTrack.disableDucking();
- assertFalse("Audio Track Ducking is Disabled",
- audioTrack.isDuckingEnabled());
- }
-
-
-
- /**
- * To test: Need a basic test case for the get value for TransitionAlpha
- * ( ie. getBlendingPercent, getMaskFilename, isInvert)
- *
- * @throws Exception
- */
- @LargeTest
- public void testTransitionAlphaBasic() throws Exception {
-
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String maskFilename = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- boolean flagForException = false;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 15000);
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2", maskFilename,
- 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaImageItem.setDuration(15000);
-
- mVideoEditor.addMediaItem(mediaVideoItem1);
- mVideoEditor.addMediaItem(mediaImageItem);
- final TransitionAlpha transition1And2 =
- mVideoEditorHelper.createTAlpha("transition1And2", mediaVideoItem1,
- mediaImageItem, 3000, Transition.BEHAVIOR_SPEED_UP,
- maskFilename, 10, false);
- mVideoEditor.addTransition(transition1And2);
- assertTrue("Transition maskFile",
- transition1And2.getMaskFilename().equals(maskFilename));
- assertEquals("Transition BlendingPercent", 10,
- transition1And2.getBlendingPercent());
- assertFalse("Transition Invert", transition1And2.isInvert());
- }
-
- /**
- * To test: NULL arguments to the Video Editor APIs
- *
- * @throws Exception
- */
- @LargeTest
- public void testNullAPIs() throws Exception {
-
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String maskFilename = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final String audioFileName = INPUT_FILE_PATH +
- "AACLC_48KHz_256Kbps_s_1_17.3gp";
- boolean flagForException = false;
-
- try {
- mVideoEditor.addAudioTrack(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Video Editor with null Audio Track", flagForException);
- flagForException = false;
- try {
- mVideoEditor.addMediaItem(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Video Editor with NULL Image Item ", flagForException);
- flagForException = false;
- try {
- mVideoEditor.addMediaItem(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Video Editor with NULL Video Item ", flagForException);
-
- MediaVideoItem mediaVideoItem1 = null;
- try {
- mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- } catch (IllegalArgumentException e) {
- assertTrue("Cannot Create Video Item", false);
- }
- mediaVideoItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
- flagForException = false;
- try {
- mediaVideoItem1.addEffect(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Video with null effect ", flagForException);
- flagForException = false;
- try {
- mediaVideoItem1.addOverlay(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Video with null overlay ", flagForException);
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2", maskFilename,
- 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaImageItem.setDuration(15000);
- mVideoEditor.addMediaItem(mediaImageItem);
- flagForException = false;
- try {
- mediaImageItem.addEffect(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Image with null effect ", flagForException);
- flagForException = false;
- try {
- mediaImageItem.addOverlay(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Image with null overlay ", flagForException);
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioFileName);
- mVideoEditor.addAudioTrack(audioTrack);
-
- flagForException = false;
- try {
- mVideoEditor.addTransition(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Added null transition ", flagForException);
-
- flagForException = false;
- try {
- mVideoEditor.addTransition(null);
- } catch(IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Added null transition ", flagForException);
-
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java
deleted file mode 100644
index 69ecf0d..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-
-
-import android.util.Log;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class VideoEditorExportTest extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
- private final String TAG = "TransitionTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private VideoEditor mVideoEditor;
-
- private VideoEditorHelper mVideoEditorHelper;
-
- // Declares the annotation for Preview Test Cases
- public @interface TransitionTests {
- }
-
- public VideoEditorExportTest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath =
- mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- /**
- * To Test export : Merge and Trim different types of Video and Image files
- */
- @LargeTest
- public void testExportMergeTrim() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename2 = INPUT_FILE_PATH
- + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final String videoItemFilename3 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
- final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/")
- + ".3gp";
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(2000, 7000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaImageItem mediaImageItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem2);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem3.setExtractBoundaries(0, 2000);
- mVideoEditor.addMediaItem(mediaVideoItem3);
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
- mediaVideoItem4.getDuration());
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final MediaImageItem mediaImageItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem5);
-
- final MediaImageItem mediaImageItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem6);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
- + mediaImageItem2.getDuration() + mediaVideoItem3.getTimelineDuration()
- + mediaVideoItem4.getTimelineDuration() + mediaImageItem5.getDuration()
- + mediaImageItem6.getDuration();
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, storyBoardDuration,
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- *To Test export : With Effect and Overlays on Different Media Items
- */
- @LargeTest
- public void testExportEffectOverlay() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename2 = INPUT_FILE_PATH
- + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
- final String videoItemFilename3 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
- final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
- final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(2000, 7000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final EffectColor effectPink =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectPink",
- 0, 2000, EffectColor.TYPE_COLOR, EffectColor.PINK);
- mediaVideoItem1.addEffect(effectPink);
-
- final EffectColor effectNegative =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectNegative",
- 3000, 4000, EffectColor.TYPE_NEGATIVE, 0);
- mediaVideoItem1.addEffect(effectNegative);
-
- final MediaImageItem mediaImageItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem2);
-
- final EffectColor effectFifties =
- mVideoEditorHelper.createEffectItem(mediaImageItem2, "effectFifties",
- 0, 3000, EffectColor.TYPE_FIFTIES, 0);
- mediaImageItem2.addEffect(effectFifties);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem3);
- mediaVideoItem3.setExtractBoundaries(0, 8000);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile,
- 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaVideoItem3, "overlay",
- mBitmap, 2000, 5000);
- mediaVideoItem3.addOverlay(overlayFrame);
-
- final EffectColor effectGreen =
- mVideoEditorHelper.createEffectItem(mediaVideoItem3, "effectGreen",
- 0, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- mediaVideoItem3.addEffect(effectGreen);
-
- final MediaVideoItem mediaVideoItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
- mediaVideoItem4.getDuration());
- mVideoEditor.addMediaItem(mediaVideoItem4);
-
- final EffectColor effectSepia =
- mVideoEditorHelper.createEffectItem(mediaVideoItem4, "effectSepia",
- 0, 2000, EffectColor.TYPE_SEPIA, 0);
- mediaVideoItem4.addEffect(effectSepia);
-
- final MediaImageItem mediaImageItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem5);
-
- final EffectColor effectGray =
- mVideoEditorHelper.createEffectItem(mediaImageItem5, "effectGray",
- 0, 2000, EffectColor.TYPE_COLOR, EffectColor.GRAY);
- mediaImageItem5.addEffect(effectGray);
-
- final MediaImageItem mediaImageItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem6);
-
- final EffectColor effectGradient =
- mVideoEditorHelper.createEffectItem(mediaImageItem6,
- "effectGradient", 0, 2000, EffectColor.TYPE_GRADIENT,
- EffectColor.PINK);
- mediaImageItem6.addEffect(effectGradient);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
- + mediaImageItem2.getDuration()
- + mediaVideoItem3.getTimelineDuration()
- + mediaVideoItem4.getTimelineDuration()
- + mediaImageItem5.getDuration()
- + mediaImageItem6.getDuration();
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, storyBoardDuration,
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- * To test export : with Image with KenBurnEffect
- */
- @LargeTest
- public void testExportEffectKenBurn() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
- imageItemFileName, 5000, imageItemRenderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
- (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
- (mediaImageItem.getWidth() / 2));
-
- final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
- mediaImageItem.getHeight());
-
- final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
- mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
- assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
- mediaImageItem.addEffect(kbEffectOnMediaItem);
-
- assertEquals("KenBurn Start Rect", startRect,
- kbEffectOnMediaItem.getStartRect());
- assertEquals("KenBurn End Rect", endRect,
- kbEffectOnMediaItem.getEndRect());
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, mediaImageItem.getDuration(),
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- * To Test Export : With Video and Image and An Audio BackGround Track
- */
- @LargeTest
- public void testExportAudio() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
- final String audioTrackFilename = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFileName, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "a1", audioTrackFilename);
- audioTrack.setExtractBoundaries(2000, 5000);
- mVideoEditor.addAudioTrack(audioTrack);
-
- audioTrack.disableDucking();
- audioTrack.enableLoop();
- audioTrack.setVolume(75);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, (mediaVideoItem.getTimelineDuration() +
- mediaImageItem.getDuration()),
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- *To Test export : With Transition on Different Media Items
- */
- @LargeTest
- public void testExportTransition() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename2 = INPUT_FILE_PATH
- + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final String videoItemFilename3 = INPUT_FILE_PATH +
- "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-
- final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
- final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
- final String maskFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
-
- final MediaVideoItem mediaItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaItem1.setExtractBoundaries(2000, 7000);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final TransitionAlpha transition1 =
- mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
- 2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
- mVideoEditor.addTransition(transition1);
-
- final MediaImageItem mediaItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final MediaVideoItem mediaItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaItem3.setExtractBoundaries(0, 8000);
- mVideoEditor.addMediaItem(mediaItem3);
-
- final TransitionSliding transition2And3 =
- mVideoEditorHelper.createTSliding("transition2", mediaItem2,
- mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- mVideoEditor.addTransition(transition2And3);
-
- final MediaVideoItem mediaItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem4);
- mediaItem4.setExtractBoundaries(0, 8000);
-
- final TransitionCrossfade transition3And4 =
- mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
- mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
- mVideoEditor.addTransition(transition3And4);
-
- final MediaImageItem mediaItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem5);
-
- final TransitionFadeBlack transition4And5 =
- mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
- mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
- mVideoEditor.addTransition(transition4And5);
-
- final MediaImageItem mediaItem6 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
- imageItemFilename3, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem6);
-
- final TransitionSliding transition5And6 =
- mVideoEditorHelper.createTSliding("transition5", mediaItem5,
- mediaItem6, 1000/*4000*/, Transition.BEHAVIOR_SPEED_UP,
- TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
- mVideoEditor.addTransition(transition5And6);
-
- final TransitionSliding transition6 =
- mVideoEditorHelper.createTSliding("transition6", mediaItem6, null,
- 1000 /*4000*/, Transition.BEHAVIOR_SPEED_UP,
- TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN);
- mVideoEditor.addTransition(transition6);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- final long storyBoardDuration = mediaItem1.getTimelineDuration()
- + mediaItem2.getTimelineDuration()
- + mediaItem3.getTimelineDuration() - transition2And3.getDuration()
- + mediaItem4.getTimelineDuration() - transition3And4.getDuration()
- + mediaItem5.getTimelineDuration() - transition4And5.getDuration()
- + mediaItem6.getTimelineDuration() - transition5And6.getDuration();
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, storyBoardDuration,
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- * To Test Export : Without any Media Items in the story Board
- *
- * @throws Exception
- */
- @LargeTest
- public void testExportWithoutMediaItems() throws Exception {
- boolean flagForException = false;
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (IllegalStateException e) {
- flagForException = true;
- }
- assertTrue("Export without any MediaItems", flagForException);
- }
-
- /**
- * To Test Export : With Media Items add and removed in the story Board
- *
- * @throws Exception
- */
- @LargeTest
- public void testExportWithoutMediaItemsAddRemove() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
- boolean flagForException = false;
-
- final MediaVideoItem mediaItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaItem1.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final MediaImageItem mediaItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 15000,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final TransitionAlpha transition1 =
- mVideoEditorHelper.createTAlpha("transition1", mediaItem1, mediaItem2,
- 3000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, false);
- mVideoEditor.addTransition(transition1);
-
- final EffectColor effectColor =
- mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 12000,
- 3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
- mediaItem2.addEffect(effectColor);
-
- mVideoEditor.removeMediaItem(mediaItem1.getId());
- mVideoEditor.removeMediaItem(mediaItem2.getId());
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (IllegalStateException e) {
- flagForException = true;
- }
- assertTrue("Export with MediaItem added and removed", flagForException);
- }
-
- /**
- * To Test Export : With Video and Image : MMS use case
- *
- * @throws Exception
- */
- @LargeTest
- public void testExportMMS() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFilename2 = INPUT_FILE_PATH
- + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
- final MediaVideoItem mediaItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaItem1.setExtractBoundaries(2000, 7000);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final TransitionAlpha transition1 =
- mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
- 2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
- mVideoEditor.addTransition(transition1);
-
- final MediaImageItem mediaItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final MediaVideoItem mediaItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaItem3.setExtractBoundaries(0, 8000);
- mVideoEditor.addMediaItem(mediaItem3);
-
- final TransitionSliding transition2And3 =
- mVideoEditorHelper.createTSliding("transition2", mediaItem2,
- mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- mVideoEditor.addTransition(transition2And3);
-
- final TransitionCrossfade transition3 =
- mVideoEditorHelper.createTCrossFade("transition3", mediaItem3, null,
- 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
- mVideoEditor.addTransition(transition3);
-
- final EffectColor effectColor =
- mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 0,
- 3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
- mediaItem2.addEffect(effectColor);
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_11_9);
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- final long storyBoardDuration = mediaItem1.getTimelineDuration()
- + mediaItem2.getTimelineDuration() + mediaItem3.getTimelineDuration()
- - transition2And3.getDuration();
-
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_144, 0, storyBoardDuration,
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- * To Test Export :Media Item having duration of 1 Hour
- *
- * @throws Exception
- */
- @Suppress
- @LargeTest
- public void testExportDuration1Hour() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH +
- "H264_BP_640x480_15fps_384kbps_60_0.mp4";
- final String outFilename = mVideoEditorHelper.createRandomFile(
- mVideoEditor.getPath() + "/") + ".3gp";
-
- final MediaVideoItem mediaItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaItem1);
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- }catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0, mediaItem1.getDuration(),
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-
- /**
- * To Test Export : Storage location having very less space (Less than 100
- * KB)
- *
- * @throws Exception
- */
- @LargeTest
- public void testExportWithStorageFull() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
- boolean flagForException = false;
-
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1", videoItemFilename1,
- MediaItem.RENDERING_MODE_BLACK_BORDER);
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- flagForException = true;
- }
- assertTrue("Error in exporting file due to lack of storage space",
- flagForException);
- }
-
- /**
- * To Test Export :Two Media Items added
- *
- * @throws Exception
- */
- @LargeTest
- public void testExportTwoVideos() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- try {
- final int[] progressUpdate = new int[100];
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
- MediaProperties.BITRATE_800K, new ExportProgressListener() {
- int i = 0;
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
- MediaProperties.HEIGHT_720, 0,
- (mediaVideoItem.getDuration()+ mediaVideoItem1.getDuration()),
- MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
deleted file mode 100644
index 7965b0a..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.Effect;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.Overlay;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.media.videoeditor.VideoEditor.PreviewProgressListener;
-import android.media.videoeditor.VideoEditor.OverlayData;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.view.SurfaceHolder;
-
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-import java.util.concurrent.TimeUnit;
-
-import android.util.Log;
-
-public class VideoEditorPreviewTest extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
- private final String TAG = "VideoEditorTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private final String PROJECT_CLASS_NAME =
- "android.media.videoeditor.VideoEditorImpl";
-
- private VideoEditor mVideoEditor;
-
- private VideoEditorHelper mVideoEditorHelper;
-
- private class EventHandler extends Handler {
- public EventHandler( Looper lp)
- {
- super(lp);
- }
- public void handleMessage(Message msg)
- {
- switch (msg.what)
- {
- default:
- MediaFrameworkTest.testInvalidateOverlay();
- }
- }
- }
- private EventHandler mEventHandler;
-
- private boolean previewStart;
- private boolean previewStop;
- private boolean previewError;
-
- /* Minimum waiting time for Semaphore to wait for release */
- private final long minWaitingTime = 3000;
-
- // Declares the annotation for Preview Test Cases
- public @interface Preview {
- }
-
- public VideoEditorPreviewTest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(looper);
-
- } else {
- //Handle error when looper can not be created.
- ;
- }
- }
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath =
- mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- protected void setPreviewStart() {
- previewStart = true;
- }
- protected void setPreviewStop() {
- previewStop = true;
- }
- protected void setPreviewError() {
- previewError = true;
- }
- protected void validatePreviewProgress(int startMs, int endMs,
- boolean loop, long duration) throws Exception {
-
- final int[] progressUpdate = new int[100];
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- previewError = false;
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- int i = 0;
- public void onProgress(Object item, int action, int progress) {
- progressUpdate[i++] = progress;
- }
- });
- mVideoEditorHelper.checkProgressCBValues(progressUpdate);
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
-
- long waitingTime = minWaitingTime;
- if (endMs == -1) {
- waitingTime += duration;
- }
- else {
- waitingTime += (endMs - startMs);
- }
- blockTillPreviewCompletes.acquire();
- try {
- mVideoEditor.startPreview(surfaceHolder, startMs, endMs, loop, 1,
- new PreviewProgressListener() {
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
-
- if ( overlayData != null) {
- if(overlayData.needsRendering()) {
- overlayData.renderOverlay(MediaFrameworkTest.mDestBitmap);
- mEventHandler.sendMessage(mEventHandler.obtainMessage(1, 2, 3));
- }
- }
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- blockTillPreviewCompletes.release();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- blockTillPreviewCompletes.release();
- }
- });
- } catch (Exception e) {
- blockTillPreviewCompletes.release();
- }
- blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
-
- mVideoEditor.stopPreview();
- assertTrue("Preview Failed to start", previewStart);
- assertTrue("Preview Failed to stop", previewStop);
- assertFalse("Preview Error occurred", previewError);
-
- blockTillPreviewCompletes.release();
- }
-
- // -----------------------------------------------------------------
- // Preview
- // -----------------------------------------------------------------
-
- /**
- *To test Preview : FULL Preview of current work (beginning till end)
- */
- @LargeTest
- public void testPreviewTheStoryBoard() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFileName3 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- previewStart = false;
- previewStop = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
- videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem2);
- mediaVideoItem2.setExtractBoundaries(0, 10000);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
- videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem3.setExtractBoundaries(0, 10000);
-
- mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
- List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
- assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
-
- mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
- assertEquals("Media Item 1 Rendering Mode",
- MediaItem.RENDERING_MODE_BLACK_BORDER,
- mediaVideoItem1.getRenderingMode());
-
- mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
- assertEquals("Media Item 2 Rendering Mode",
- MediaItem.RENDERING_MODE_BLACK_BORDER,
- mediaVideoItem2.getRenderingMode());
-
- mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
- assertEquals("Media Item 3 Rendering Mode",
- MediaItem.RENDERING_MODE_STRETCH,
- mediaVideoItem3.getRenderingMode());
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
- assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
- mVideoEditor.getAspectRatio());
-
- validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- * To test Preview : Preview of start + 10 sec till end of story board
- */
- @LargeTest
- public void testPreviewTheStoryBoardFromDuration() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
- final String videoItemFileName3 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
- videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
- videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem3.setExtractBoundaries(0, 10000);
-
- mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
-
- List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
- assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
- mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- assertEquals("Media Item 1 Rendering Mode",
- MediaItem.RENDERING_MODE_BLACK_BORDER,
- mediaVideoItem1.getRenderingMode());
- mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- assertEquals("Media Item 2 Rendering Mode",
- MediaItem.RENDERING_MODE_BLACK_BORDER,
- mediaVideoItem2.getRenderingMode());
- mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
-
- assertEquals("Media Item 3 Rendering Mode",
- MediaItem.RENDERING_MODE_STRETCH,
- mediaVideoItem3.getRenderingMode());
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
- assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
- mVideoEditor.getAspectRatio());
-
- validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- * To test Preview : Preview of current Effects applied
- */
- @LargeTest
- public void testPreviewOfEffects() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final EffectColor effectNegative =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1,
- "effectNegative", 0, 2000, EffectColor.TYPE_NEGATIVE, 0);
- mediaVideoItem1.addEffect(effectNegative);
-
- final EffectColor effectGreen =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectGreen",
- 2000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- mediaVideoItem1.addEffect(effectGreen);
-
- final EffectColor effectFifties =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1,
- "effectFifties", 5000, 4000, EffectColor.TYPE_FIFTIES, 0);
- mediaVideoItem1.addEffect(effectFifties);
-
- List<Effect> effectList = mediaVideoItem1.getAllEffects();
- assertEquals("Effect List Size", 3, effectList.size());
- assertEquals("Effect negative", effectNegative, effectList.get(0));
- assertEquals("Effect Green", effectGreen, effectList.get(1));
- assertEquals("Effect Fifties", effectFifties, effectList.get(2));
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
- assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_4_3,
- mVideoEditor.getAspectRatio());
-
- final long storyboardDuration = mVideoEditor.getDuration() ;
- validatePreviewProgress(0, (int)(storyboardDuration/2), false, (storyboardDuration/2));
-
- assertEquals("Removing Effect : Negative", effectNegative,
- mediaVideoItem1.removeEffect(effectNegative.getId()));
-
- effectList = mediaVideoItem1.getAllEffects();
-
- assertEquals("Effect List Size", 2, effectList.size());
- assertEquals("Effect Green", effectGreen, effectList.get(0));
- assertEquals("Effect Fifties", effectFifties, effectList.get(1));
-
- validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- *To test Preview : Preview of current Transitions applied (with multiple
- * generatePreview)
- */
- @LargeTest
- public void testPreviewWithTransition() throws Exception {
-
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
- final String imageItemFileName1 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
- final String maskFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
- previewStart = false;
- previewStop = false;
- previewError = false;
-
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFileName1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem2.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionCrossfade transition1And2CrossFade =
- mVideoEditorHelper.createTCrossFade("transition_1_2_CF",
- mediaVideoItem1, mediaImageItem1, 2000,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition1And2CrossFade);
-
- final TransitionAlpha transition2And3Alpha =
- mVideoEditorHelper.createTAlpha("transition_2_3", mediaImageItem1,
- mediaVideoItem2, 4000, Transition.BEHAVIOR_SPEED_UP,
- maskFilename, 50, true);
- mVideoEditor.addTransition(transition2And3Alpha);
-
- final TransitionFadeBlack transition1FadeBlack =
- mVideoEditorHelper.createTFadeBlack("transition_1FB", null,
- mediaVideoItem1, 2000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition1FadeBlack);
-
- List<Transition> transitionList = mVideoEditor.getAllTransitions();
- assertEquals("Transition List Size", 3, transitionList.size());
- assertEquals("Transition 1", transition1And2CrossFade,
- transitionList.get(0));
- assertEquals("Transition 2", transition2And3Alpha, transitionList.get(1));
- assertEquals("Transition 3", transition1FadeBlack, transitionList.get(2));
-
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_3_2);
-
- final int[] progressValues = new int[300];
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- int i = 0;
-
- public void onProgress(Object item, int action, int progress) {
- if (item instanceof TransitionCrossfade) {
- progressValues[i] = progress;
- assertEquals("Object", item, transition1And2CrossFade);
- assertEquals("Action", action,
- MediaProcessingProgressListener.ACTION_ENCODE);
- } else if (item instanceof TransitionAlpha) {
- progressValues[i] = progress;
- assertEquals("Object", item, transition2And3Alpha);
- assertEquals("Action", action,
- MediaProcessingProgressListener.ACTION_ENCODE);
- } else if (item instanceof TransitionFadeBlack) {
- progressValues[i] = progress;
- assertEquals("Object", item, transition1FadeBlack);
- assertEquals("Action", action,
- MediaProcessingProgressListener.ACTION_ENCODE);
- }
- i++;
- }
- });
-
- mVideoEditorHelper.checkProgressCBValues(progressValues);
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- /* As transition takes more time buffer of 10 sec is added */
- long waitingTime = minWaitingTime + 10000 + 10000;
-
- blockTillPreviewCompletes.acquire();
- try {
- mVideoEditor.startPreview(surfaceHolder, 0, 10000, false, 1,
- new PreviewProgressListener() {
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- blockTillPreviewCompletes.release();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- blockTillPreviewCompletes.release();
- }
- });
- } catch (Exception e) {
- blockTillPreviewCompletes.release();
- }
- blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
- mVideoEditor.stopPreview();
- blockTillPreviewCompletes.release();
- assertTrue("Preview Failed to start", previewStart);
- assertTrue("Preview Failed to stop", previewStop);
- assertFalse("Preview Error occurred", previewError);
-
- assertEquals("Removing Transition " + transition1And2CrossFade.getId(),
- transition1And2CrossFade,
- mVideoEditor.removeTransition(transition1And2CrossFade.getId()));
- transitionList = mVideoEditor.getAllTransitions();
- assertEquals("Transition List Size", 2, transitionList.size());
- assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
- assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
-
- validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
-
-
- final TransitionSliding transition1And2Sliding =
- mVideoEditorHelper.createTSliding("transition_1_2Sliding",
- mediaVideoItem1, mediaImageItem1, 4000,
- Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
- mVideoEditor.addTransition(transition1And2Sliding);
-
- transitionList = mVideoEditor.getAllTransitions();
- assertEquals("Transition List Size", 3, transitionList.size());
- assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
- assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
- assertEquals("Transition 3", transition1And2Sliding,
- transitionList.get(2));
-
- validatePreviewProgress(5000, -1, false, (mVideoEditor.getDuration()));
-
- }
-
- /**
- * To test Preview : Preview of current Overlay applied
- */
- @LargeTest
- public void testPreviewWithOverlay() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String overlayFilename1 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final String overlayFilename2 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay2.png";
- final int previewFrom = 5000;
- final int previewTo = 10000;
- final boolean previewLoop = false;
- final int previewCallbackFrameCount = 1;
- final int setAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- boolean flagForException = false;
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem);
- mediaVideoItem.setExtractBoundaries(0, 10000);
-
- final Bitmap mBitmap1 = mVideoEditorHelper.getBitmap(overlayFilename1,
- 640, 480);
- final OverlayFrame overlayOnMvi1 =
- mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi1",
- mBitmap1, 0, 5000);
- mediaVideoItem.addOverlay(overlayOnMvi1);
-
- final Bitmap mBitmap2 = mVideoEditorHelper.getBitmap(overlayFilename2,
- 640, 480);
- final OverlayFrame overlayOnMvi2 =
- mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi2",
- mBitmap2, 5000, 9000);
- mediaVideoItem.addOverlay(overlayOnMvi2);
-
- List<Overlay> overlayList = mediaVideoItem.getAllOverlays();
- assertEquals("Overlay Size", 2, overlayList.size());
- assertEquals("Overlay 1", overlayOnMvi1, overlayList.get(0));
- assertEquals("Overlay 2", overlayOnMvi2, overlayList.get(1));
-
- mVideoEditor.setAspectRatio(setAspectRatio);
-
- validatePreviewProgress(0 /* previewFrom */, -1, previewLoop,
- mVideoEditor.getDuration());
- }
-
- /**
- * To test Preview : Preview of current Trim applied (with default aspect
- * ratio)
- */
- @LargeTest
- public void testPreviewWithTrim() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, MediaItem.RENDERING_MODE_CROPPING);
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- boolean flagForException = false;
- previewStart = false;
- previewStop = false;
- mediaVideoItem.setExtractBoundaries(mediaVideoItem.getDuration() / 2,
- mediaVideoItem.getDuration());
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- validatePreviewProgress(1000, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- * To test Preview : Preview of current work having Overlay and Effect
- * applied
- */
-
- @LargeTest
- public void testPreviewWithOverlayEffectKenBurn() throws Exception {
-
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final String overlayFilename = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaImageItem mediaImageItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFileName, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem2);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem3);
-
- final EffectColor effectColor =
- mVideoEditorHelper.createEffectItem(mediaVideoItem1, "Effect1",
- 1000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- mediaVideoItem1.addEffect(effectColor);
-
- final Rect startRect = new Rect((mediaImageItem2.getHeight() / 3),
- (mediaImageItem2.getWidth() / 3), (mediaImageItem2.getHeight() / 2),
- (mediaImageItem2.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaImageItem2.getWidth(),
- mediaImageItem2.getHeight());
-
- final EffectKenBurns kbeffectOnMI2 = new EffectKenBurns(mediaImageItem2,
- "KBOnM2", startRect, endRect, 0, 10000);
- assertNotNull("EffectKenBurns", kbeffectOnMI2);
- mediaImageItem2.addEffect(kbeffectOnMI2);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFilename,
- 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaVideoItem3, "OverlayID",
- mBitmap, (mediaImageItem2.getDuration() / 4),
- (mediaVideoItem3.getDuration() / 3));
- mediaVideoItem3.addOverlay(overlayFrame);
-
- validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- *To test Preview : Export during preview
- */
- @LargeTest
- public void testPreviewDuringExport() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- previewStart = false;
- previewStop = false;
- previewError = false;
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- long waitingTime = minWaitingTime + mVideoEditor.getDuration();
-
-
- blockTillPreviewCompletes.acquire();
- final String fileName = mVideoEditor.getPath() + "/test.3gp";
- final int height = MediaProperties.HEIGHT_480;
- final int bitrate = MediaProperties.BITRATE_512K;
-
- try {
- mVideoEditor.export(fileName, height, bitrate,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve,
- String outFileName,int progress) {
-
- }
- });
- } catch (IOException e) {
- assertTrue("UnExpected Error in Export" +
- e.toString(), false);
- }
-
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- try {
-
- mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1,
- new PreviewProgressListener() {
-
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- blockTillPreviewCompletes.release();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- blockTillPreviewCompletes.release();
- }
- });
-
- } catch (Exception e) {
- blockTillPreviewCompletes.release();
- }
- blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
- mVideoEditor.stopPreview();
- assertTrue("Preview Failed to start", previewStart);
- assertTrue("Preview Failed to stop", previewStop);
- assertFalse("Preview Error occurred", previewError);
-
- blockTillPreviewCompletes.release();
- }
-
- /**
- * To test Preview : Preview of current Effects applied (with from time >
- * total duration)
- */
- @LargeTest
- public void testPreviewWithDurationGreaterThanMediaDuration()
- throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_192kbps_1_5.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- boolean flagForException = false;
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName, renderingMode);
- try {
- mediaVideoItem1.setExtractBoundaries(0, 20000);
- } catch (Exception e) {
- assertTrue("Exception during setExtract Boundaries", false);
- }
- mVideoEditor.addMediaItem(mediaVideoItem1);
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- long waitingTime = minWaitingTime + (mVideoEditor.getDuration() - 30000);
- if(waitingTime < 0)
- {
- waitingTime = minWaitingTime;
- }
-
- blockTillPreviewCompletes.acquire();
- try {
- mVideoEditor.startPreview(surfaceHolder, 30000, -1, true, 1,
- new PreviewProgressListener() {
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- blockTillPreviewCompletes.release();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- blockTillPreviewCompletes.release();
- }
- });
-
- } catch (IllegalArgumentException e) {
- blockTillPreviewCompletes.release();
- flagForException = true;
- }
- blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
- assertTrue("Expected Error in Preview", flagForException);
- mVideoEditor.stopPreview();
- blockTillPreviewCompletes.release();
- }
-
- /**
- * To test Preview : Preview of current Effects applied (with Render Preview
- * Frame)
- */
- @LargeTest
- public void testPreviewWithRenderPreviewFrame() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final Semaphore blockTillPreviewCompletes = new Semaphore(1);
- boolean flagForException = false;
- OverlayData overlayData1 = new OverlayData();
- previewStart = false;
- previewStop = false;
-
- final String overlayFilename1 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor,
- "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final EffectColor effectPink =
- mVideoEditorHelper.createEffectItem(mediaVideoItem,
- "effectNegativeOnMvi", 1000, 3000, EffectColor.TYPE_COLOR,
- EffectColor.PINK);
- mediaVideoItem.addEffect(effectPink);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
-
- assertEquals("Render preview Frame at 5 Sec", 5000,
- mVideoEditor.renderPreviewFrame(surfaceHolder, 5000,
- overlayData1));
-
- assertEquals("Render preview Frame at 7 Sec", 7000,
- mVideoEditor.renderPreviewFrame(surfaceHolder, 7000,
- overlayData1));
-
- validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- * To test Preview : Preview of current work from selected jump location
- * till end with Audio Track
- */
- @LargeTest
- public void testPreviewWithEndAudioTrack() throws Exception {
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final String audioFilename = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-
- boolean flagForException = false;
- previewStart = false;
- previewStop = false;
- final MediaImageItem mediaImageItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- imageItemFilename1, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem1);
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem.setExtractBoundaries(1000, 8000);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaImageItem mediaImageItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem2);
-
- final AudioTrack audioTrack =
- mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
- mVideoEditor.addAudioTrack(audioTrack);
-
- List<AudioTrack> audioList = mVideoEditor.getAllAudioTracks();
- assertEquals("Audio Track List size", 1, audioList.size());
- assertEquals("Audio Track", audioTrack, audioList.get(0));
- mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
-
- validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
- }
-
- /**
- * To test render Preview Frame
- */
- @LargeTest
- public void testRenderPreviewFrame() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH
- + "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH
- + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
- final String videoItemFileName3 = INPUT_FILE_PATH
- + "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String imageItemFilename1 = INPUT_FILE_PATH
- + "IMG_1600x1200.jpg";
- final String imageItemFilename2 = INPUT_FILE_PATH
- + "IMG_176x144.jpg";
- final String audioFilename = INPUT_FILE_PATH
- + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- OverlayData overlayData1 = new OverlayData();
- previewStart = false;
- previewStop = false;
- final MediaVideoItem mediaVideoItem1 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 4,
- mediaVideoItem2.getDuration() / 2);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final MediaVideoItem mediaVideoItem3 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
- videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 2,
- mediaVideoItem2.getDuration());
- mVideoEditor.addMediaItem(mediaVideoItem3);
-
- final MediaImageItem mediaImageItem4 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
- imageItemFilename1, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- final MediaImageItem mediaImageItem5 =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
- imageItemFilename2, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
- List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 3, mediaList.size());
-
- mVideoEditor.insertMediaItem(mediaImageItem4, mediaVideoItem2.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 4, mediaList.size());
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
- assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(3));
-
- mVideoEditor.insertMediaItem(mediaImageItem5, mediaImageItem4.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 5, mediaList.size());
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
- assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
- assertEquals("Media item 5", mediaImageItem5, mediaList.get(3));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
- mVideoEditor.moveMediaItem(mediaVideoItem1.getId(),
- mediaImageItem5.getId());
- mediaList = mVideoEditor.getAllMediaItems();
- assertEquals("Media Item List Size", 5, mediaList.size());
- assertEquals("Media item 2", mediaVideoItem2, mediaList.get(0));
- assertEquals("Media item 4", mediaImageItem4, mediaList.get(1));
- assertEquals("Media item 5", mediaImageItem5, mediaList.get(2));
- assertEquals("Media item 1", mediaVideoItem1, mediaList.get(3));
- assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
- final TransitionCrossfade transition2And4CrossFade =
- mVideoEditorHelper.createTCrossFade("transition2And4CrossFade",
- mediaVideoItem2, mediaImageItem4, 2000,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition2And4CrossFade);
-
- final TransitionCrossfade transition1And3CrossFade =
- mVideoEditorHelper.createTCrossFade("transition1And3CrossFade",
- mediaVideoItem1, mediaVideoItem3, 5000,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(transition1And3CrossFade);
-
- final AudioTrack audioTrack =
- mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
- audioTrack.setExtractBoundaries(0, 2000);
- mVideoEditor.addAudioTrack(audioTrack);
-
- audioTrack.enableLoop();
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
-
- mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/4, overlayData1);
- Thread.sleep(1000);
- mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/2, overlayData1);
- Thread.sleep(1000);
- mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration(), overlayData1);
-
- }
-
- /**
- * To Test Preview : Without any Media Items in the story Board
- */
- @LargeTest
- public void testStartPreviewWithoutMediaItems() throws Exception {
- boolean flagForException = false;
-
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- try{
- mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
- new PreviewProgressListener() {
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- }
- });
- }catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Preview without Media Items", flagForException);
- }
-
- /**
- * To Test Preview : Add Media and Remove Media Item (Without any Media
- * Items in the story Board)
- */
- @LargeTest
- public void testStartPreviewAddRemoveMediaItems() throws Exception {
- final String videoItemFilename1 = INPUT_FILE_PATH
- + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
- final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String alphaFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
- boolean flagForException = false;
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
- videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mediaVideoItem.setExtractBoundaries(0, 15000);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaImageItem mediaImageItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
- imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final TransitionAlpha transition1And2 =
- mVideoEditorHelper.createTAlpha("transition", mediaVideoItem,
- mediaImageItem, 3000, Transition.BEHAVIOR_SPEED_UP,
- alphaFilename, 10, false);
- mVideoEditor.addTransition(transition1And2);
-
- final EffectColor effectColor =
- mVideoEditorHelper.createEffectItem(mediaImageItem, "effect", 5000,
- 3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
- mediaImageItem.addEffect(effectColor);
-
- assertEquals("removing Media item 1", mediaVideoItem,
- mVideoEditor.removeMediaItem(mediaVideoItem.getId()));
- assertEquals("removing Media item 2", mediaImageItem,
- mVideoEditor.removeMediaItem(mediaImageItem.getId()));
-
- try{
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
- new PreviewProgressListener() {
- public void onProgress(VideoEditor videoEditor, long timeMs,
- OverlayData overlayData) {
- }
- public void onStart(VideoEditor videoEditor) {
- setPreviewStart();
- }
- public void onStop(VideoEditor videoEditor) {
- setPreviewStop();
- }
- public void onError(VideoEditor videoEditor, int error) {
- setPreviewError();
- }
- });
- }catch (IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue("Preview with removed Media Items", flagForException);
-
- }
-
- /**
- * To test Preview : Preview of current Effects applied (with Render Preview
- * Frame)
- */
- @LargeTest
- public void testPreviewWithRenderPreviewFrameWithoutGenerate() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- boolean flagForException = false;
- long duration = 0;
- OverlayData overlayData1 = new OverlayData();
-
- final MediaVideoItem mediaVideoItem =
- mVideoEditorHelper.createMediaItem(mVideoEditor,
- "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final SurfaceHolder surfaceHolder =
- MediaFrameworkTest.mSurfaceView.getHolder();
- duration = mVideoEditor.getDuration();
- /* RenderPreviewFrame returns -1 to indicate last frame */
- try {
- mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
- overlayData1);
- } catch ( IllegalStateException e) {
- flagForException = true;
- }
- assertTrue (" Render Preview Frame without generate", flagForException);
- duration = mVideoEditor.getDuration() + 1000;
- try {
- mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
- overlayData1);
- } catch ( IllegalArgumentException e) {
- flagForException = true;
- }
- assertTrue (" Preview time greater than duration", flagForException);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
deleted file mode 100644
index d15a535..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.performance;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.Writer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-
-import android.util.Log;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-/**
- * Junit / Instrumentation - performance measurement for media player and
- * recorder
- */
-public class VideoEditorPerformance extends
- ActivityInstrumentationTestCase<MediaFrameworkTest> {
-
- private final String TAG = "VideoEditorPerformance";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
- "VideoEditorPerformance.txt";
-
- public VideoEditorPerformance() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- }
-
- private final String PROJECT_CLASS_NAME =
- "android.media.videoeditor.VideoEditorImpl";
- private VideoEditor mVideoEditor;
- private VideoEditorHelper mVideoEditorHelper;
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath =
- mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- private void writeTimingInfo(String testCaseName, String[] information)
- throws Exception {
- File outFile = new File(VIDEOEDITOR_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(outFile, true));
- output.write(testCaseName + "\n\t");
- for (int i = 0; i < information.length; i++) {
- output.write(information[i]);
- }
- output.write("\n\n");
- output.close();
- }
-
- private final int NUM_OF_ITERATIONS=20;
-
- private int calculateTimeTaken(long beginTime, int numIterations)
- throws Exception {
- final long duration2 = SystemClock.uptimeMillis();
- final long durationToCreateMediaItem = (duration2 - beginTime);
- final int timeTaken1 = (int)(durationToCreateMediaItem / numIterations);
- return (timeTaken1);
- }
-
- private void createVideoItems(MediaVideoItem[] mediaVideoItem,
- String videoItemFileName, int renderingMode, int startTime, int endTime) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
- videoItemFileName, renderingMode);
- mediaVideoItem[i].setExtractBoundaries(startTime, endTime);
- } catch (Exception e1) {
- assertTrue(
- "Can not create an object of Video Item with file name = "
- + videoItemFileName + "------ID:m" + i + " Issue = "
- + e1.toString(), false);
- }
- }
- }
-
- private void addVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mVideoEditor.addMediaItem(mediaVideoItem[i]);
- } catch (Exception e1) {
- assertTrue(
- "Can not add an object of Video Item with ID:m" + i +
- " Issue = " + e1.toString(), false);
- }
- }
- }
-
- private void removeVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mVideoEditor.removeMediaItem(mediaVideoItem[i].getId());
- } catch (Exception e1) {
- assertTrue(
- "Can not Remove an object of Video Item with ID:m" + i +
- " Issue = " + e1.toString(), false);
- }
- }
- }
-
- private void createImageItems(MediaImageItem[] mIi,
- String imageItemFileName, int renderingMode, int duration) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mIi[i] = new MediaImageItem(mVideoEditor, "m" + i,
- imageItemFileName, duration, renderingMode);
- } catch (Exception e1) {
- assertTrue( " Cannot create Image Item", false);
- }
- }
- }
-
- private void addImageItems(MediaImageItem[] mIi) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mVideoEditor.addMediaItem(mIi[i]);
- } catch (Exception e1) {
- assertTrue("Cannot add Image item", false);
- }
- }
- }
-
- private void removeImageItems(MediaImageItem[] mIi) throws Exception {
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- try {
- mVideoEditor.removeMediaItem(mIi[i].getId());
- } catch (Exception e1) {
- assertTrue("Cannot remove image item", false);
- }
- }
- }
- /**
- * To test the performance of adding and removing the video media item
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceAddRemoveVideoItem() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int videoItemStartTime = 0;
- final int videoItemEndTime = 5000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[3];
- final MediaVideoItem[] mediaVideoItem =
- new MediaVideoItem[NUM_OF_ITERATIONS];
- int timeTaken = 0;
- long startTime = 0;
-
- /** Time Take for creation of Media Video Item */
- startTime = SystemClock.uptimeMillis();
- createVideoItems(mediaVideoItem, videoItemFileName, renderingMode,
- videoItemStartTime, videoItemEndTime);
-
- timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
- loggingInfo[0] = "Time taken to Create Media Video Item :" +
- timeTaken;
-
- /** Time Take for Addition of Media Video Item */
- startTime = SystemClock.uptimeMillis();
- addVideoItems(mediaVideoItem);
- timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
- loggingInfo[1] = "\n\tTime taken to Add Media Video Item :"
- + timeTaken;
-
- /** Time Take for Removal of Media Video Item */
- startTime = SystemClock.uptimeMillis();
- removeVideoItems(mediaVideoItem);
- timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
- loggingInfo[2] = "\n\tTime taken to remove Media Video Item :"
- + timeTaken;
-
- writeTimingInfo("testPerformanceAddRemoveVideoItem (in mSec)", loggingInfo);
- }
-
- /**
- * To test the performance of adding and removing the image media item
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceAddRemoveImageItem() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final int imageItemDuration = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[3];
- final MediaImageItem[] mediaImageItem =
- new MediaImageItem[NUM_OF_ITERATIONS];
- int timeTaken = 0;
-
- long beginTime = SystemClock.uptimeMillis();
- createImageItems(mediaImageItem, imageItemFileName, renderingMode,
- imageItemDuration);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[0] = "Time taken to Create Media Image Item :" +
- timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- addImageItems(mediaImageItem);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[1] = "\n\tTime taken to add Media Image Item :" +
- timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- removeImageItems(mediaImageItem);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[2] = "\n\tTime taken to remove Media Image Item :"
- + timeTaken;
-
- writeTimingInfo("testPerformanceAddRemoveImageItem (in mSec)",
- loggingInfo);
- }
-
- /**
- * To test the performance of adding and removing the transition
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceAddRemoveTransition() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int videoItemStartTime1 = 0;
- final int videoItemEndTime1 = 20000;
- final String videoItemFileName2 = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int videoItemStartTime2 = 0;
- final int videoItemEndTime2 = 20000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int transitionDuration = 5000;
- final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
- final String[] loggingInfo = new String[3];
- int timeTaken = 0;
-
- final MediaVideoItem[] mediaVideoItem =
- new MediaVideoItem[(NUM_OF_ITERATIONS *10) + 1];
-
- for (int i = 0; i < (NUM_OF_ITERATIONS *10); i+=2) {
- try {
- mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
- videoItemFileName1, renderingMode);
- mediaVideoItem[i+1] = new MediaVideoItem(mVideoEditor,
- "m" + (i+1), videoItemFileName2, renderingMode);
- mediaVideoItem[i].setExtractBoundaries(videoItemStartTime1,
- videoItemEndTime1);
- mediaVideoItem[i+1].setExtractBoundaries(videoItemStartTime2,
- videoItemEndTime2);
- } catch (Exception e1) {
- assertTrue("Can not create Video Object Item with file name = "
- + e1.toString(), false);
- }
- mVideoEditor.addMediaItem(mediaVideoItem[i]);
- mVideoEditor.addMediaItem(mediaVideoItem[i+1]);
- }
- mediaVideoItem[(NUM_OF_ITERATIONS *10)] = new MediaVideoItem(mVideoEditor,
- "m" + (NUM_OF_ITERATIONS *10), videoItemFileName1, renderingMode);
- mediaVideoItem[(NUM_OF_ITERATIONS *10)].setExtractBoundaries(
- videoItemStartTime1, videoItemEndTime1);
- mVideoEditor.addMediaItem(mediaVideoItem[(NUM_OF_ITERATIONS *10)]);
- final TransitionCrossfade tranCrossfade[] =
- new TransitionCrossfade[(NUM_OF_ITERATIONS *10)];
-
- long beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
- tranCrossfade[i] = new TransitionCrossfade("transition" + i,
- mediaVideoItem[i], mediaVideoItem[i+1], transitionDuration,
- transitionBehavior);
- }
- timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
- loggingInfo[0] = "Time taken to Create CrossFade Transition :" +
- timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
- mVideoEditor.addTransition(tranCrossfade[i]);
- }
- timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
- loggingInfo[1] = "\n\tTime taken to add CrossFade Transition :" +
- timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
- assertEquals("Removing Transitions", tranCrossfade[i], mVideoEditor
- .removeTransition(tranCrossfade[i].getId()));
- }
- timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
- loggingInfo[2] = "\n\tTime taken to remove CrossFade Transition :" +
- timeTaken;
-
- writeTimingInfo("testPerformanceAddRemoveTransition (in mSec)", loggingInfo);
- }
-
- /**
- * To test performance of Export
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceExport() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int outHeight = MediaProperties.HEIGHT_480;
- final int outBitrate = MediaProperties.BITRATE_256K;
- final int outVcodec = MediaProperties.VCODEC_H264;
- final String[] loggingInfo = new String[1];
- final String outFilename = mVideoEditorHelper
- .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
- final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp";
- final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
- final String videoItemFileName3 = INPUT_FILE_PATH +
- "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
- final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
- final String audioTrackFilename = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- final String maskFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
-
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFileName1, renderingMode);
- mediaItem1.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2", imageItemFileName1, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3", videoItemFileName2, renderingMode);
- mediaItem3.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaItem3);
-
- final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
- "m4", imageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem4);
-
- final MediaVideoItem mediaItem5 = new MediaVideoItem(mVideoEditor,
- "m5", videoItemFileName3, renderingMode);
- mediaItem5.setExtractBoundaries(0, 20000);
- mVideoEditor.addMediaItem(mediaItem5);
- /**
- * 7.Add TransitionAlpha, Apply this Transition as Begin for Media Item 1
- * with duration = 2 sec behavior = BEHAVIOR_LINEAR, mask file name =
- * TransitionSpiral_QVGA.jpg , blending percent = 50%, invert = true;
- * */
- final TransitionAlpha transition1 =
- mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
- 2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
- mVideoEditor.addTransition(transition1);
-
- /**
- * 8.Add Transition Sliding between MediaItem 2 and 3 ,
- * Sliding Direction = DIRECTION_RIGHT_OUT_LEFT_IN,
- * behavior = BEHAVIOR_MIDDLE_FAST and duration = 4sec
- * */
- final TransitionSliding transition2And3 =
- mVideoEditorHelper.createTSliding("transition2", mediaItem2,
- mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
- mVideoEditor.addTransition(transition2And3);
-
- /**
- * 9.Add Transition Crossfade between Media Item 3 and 4,
- * behavior = BEHAVIOR_MIDDLE_SLOW, duration = 3.5 sec
- * */
- final TransitionCrossfade transition3And4 =
- mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
- mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
- mVideoEditor.addTransition(transition3And4);
-
- /**
- * 10.Add Transition Fadeblack between Media Item 4 and 5,
- * behavior = BEHAVIOR_SPEED_DOWN, duration = 3.5 sec
- * */
- final TransitionFadeBlack transition4And5 =
- mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
- mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
- mVideoEditor.addTransition(transition4And5);
-
- /**
- * 11.Add Effect 1 type="TYPE_SEPIA" to the MediaItem 1,
- * start time=1sec and duration =4secs
- * */
- final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
- mediaItem1, "effect1", 1000, 4000, EffectColor.TYPE_SEPIA, 0);
- mediaItem1.addEffect(effectColor1);
-
- /**
- * 12.Add Overlay 1 to the MediaItem 3: Frame Overlay with start time = 1 sec
- * duration = 4 sec with item = IMG_640x480_Overlay1.png
- * */
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFile, 640,
- 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem3, "overlay",
- mBitmap, 1000, 4000);
- mediaItem3.addOverlay(overlayFrame);
- /**
- * 13.Add Effect 2 type="TYPE_NEGATIVE" to the MediaItem 2,
- * start time=8sec and duration =2secs
- * */
- final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem(
- mediaItem2, "effect2", 8000, 2000, EffectColor.TYPE_NEGATIVE, 0);
- mediaItem2.addEffect(effectColor2);
- /**
- * 14.Add Effect 3 type="TYPE_COLOR" to the MediaItem 3, color param = "PINK",
- * start time=5 sec and duration =3secs
- * */
- final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem(
- mediaItem3, "effect3", 5000, 3000, EffectColor.TYPE_COLOR,
- EffectColor.PINK);
- mediaItem3.addEffect(effectColor3);
- /**
- * 15.Add Effect 4 type="TYPE_FIFTIES" to the MediaItem 4,
- * start time=2 sec and duration =1secs
- * */
- final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem(
- mediaItem4, "effect4", 2000, 1000, EffectColor.TYPE_FIFTIES, 0);
- mediaItem4.addEffect(effectColor4);
- /**
- * 16.Add KenBurnsEffect for MediaItem 4 with
- * duration = 3 sec and startTime = 4 sec
- * StartRect
- * left = org_height/3 ; top = org_width/3
- * bottom = org_width/2 ; right = org_height/2
- * EndRect
- * left = 0 ; top = 0
- * bottom = org_height; right = org_width
- * */
-
- final Rect startRect = new Rect((mediaItem4.getHeight() / 3),
- (mediaItem4.getWidth() / 3), (mediaItem4.getHeight() / 2),
- (mediaItem4.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaItem4.getWidth(),
- mediaItem4.getHeight());
- final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
- mediaItem4, "KBOnM2", startRect, endRect,4000 , 3000);
- mediaItem4.addEffect(kbEffectOnMediaItem);
-
- /** 17.Add Audio Track,Set extract boundaries o to 10 sec.
- * */
- final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
- mVideoEditor, "audioTrack", audioTrackFilename);
- mVideoEditor.addAudioTrack(audioTrack);
- /** 18.Enable Looping for Audio Track.
- * */
- audioTrack.enableLoop();
- int timeTaken = 0;
- final long beginTime = SystemClock.uptimeMillis();
- try {
- mVideoEditor.export(outFilename, outHeight, outBitrate,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve,
- String outFileName, int progress) {
- }
- });
- } catch (Exception e) {
- assertTrue("Error in Export" + e.toString(), false);
- }
- mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-
- timeTaken = calculateTimeTaken(beginTime, 1);
- loggingInfo[0] = "Time taken to do ONE export of storyboard duration "
- + mVideoEditor.getDuration() + " is :" + timeTaken;
-
- writeTimingInfo("testPerformanceExport (in mSec)", loggingInfo);
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- }
-
-
- /**
- * To test the performance of thumbnail extraction
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceThumbnailVideoItem() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int videoItemStartTime = 0;
- final int videoItemEndTime = 20000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[1];
-
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFileName, renderingMode);
- mediaVideoItem.setExtractBoundaries(videoItemStartTime,
- videoItemEndTime);
-
- int timeTaken = 0;
- long beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- mediaVideoItem.getThumbnail(mediaVideoItem.getWidth() / 2,
- mediaVideoItem.getHeight() / 2, i);
- }
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[0] = "Duration taken to get Video Thumbnails :" +
- timeTaken;
-
- writeTimingInfo("testPerformanceThumbnailVideoItem (in mSec)", loggingInfo);
- }
-
- /**
- * To test the performance of adding and removing the overlay to media item
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceOverlayVideoItem() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int videoItemStartTime1 = 0;
- final int videoItemEndTime1 = 10000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String overlayFilename = INPUT_FILE_PATH
- + "IMG_640x480_Overlay1.png";
- final int overlayStartTime = 1000;
- final int overlayDuration = 5000;
-
- final String[] loggingInfo = new String[2];
- MediaVideoItem mediaVideoItem = null;
-
- try {
- mediaVideoItem = new MediaVideoItem(mVideoEditor, "m0",
- videoItemFileName1, renderingMode);
- mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
- videoItemEndTime1);
- } catch (Exception e1) {
- assertTrue("Can not create Video Item with file name = "
- + e1.toString(), false);
- }
- final OverlayFrame overlayFrame[] = new OverlayFrame[NUM_OF_ITERATIONS];
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(overlayFilename,
- 640, 480);
- int timeTaken = 0;
- long beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- overlayFrame[i] = new OverlayFrame(mediaVideoItem, "overlay" + i,
- mBitmap, overlayStartTime, overlayDuration);
- mediaVideoItem.addOverlay(overlayFrame[i]);
- }
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[0] = "Time taken to add & create Overlay :" + timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- assertEquals("Removing Overlays", overlayFrame[i],
- mediaVideoItem.removeOverlay((overlayFrame[i].getId())));
- }
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[1] = "\n\tTime taken to remove Overlay :" +
- timeTaken;
-
- writeTimingInfo("testPerformanceOverlayVideoItem (in mSec)", loggingInfo);
- }
-
- /**
- * To test the performance of get properties of a Video media item
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceVideoItemProperties() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int videoItemStartTime1 = 0;
- final int videoItemEndTime1 = 10100;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int fileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int duration = 77366;
- final int videoBitrate = 3169971;
- final int fps = 30;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int width = 1080;
- final int height = MediaProperties.HEIGHT_720;
- int timeTaken = 0;
- final String[] loggingInfo = new String[1];
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "m0", videoItemFileName1, renderingMode);
- mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
- videoItemEndTime1);
- long beginTime = SystemClock.uptimeMillis();
- for (int i = 0; i < (NUM_OF_ITERATIONS*10); i++) {
- try {
- assertEquals("Aspect Ratio Mismatch",
- aspectRatio, mediaVideoItem.getAspectRatio());
- assertEquals("File Type Mismatch",
- fileType, mediaVideoItem.getFileType());
- assertEquals("VideoCodec Mismatch",
- videoCodecType, mediaVideoItem.getVideoType());
- assertEquals("duration Mismatch",
- duration, mediaVideoItem.getDuration());
- assertEquals("Video Profile ",
- videoProfile, mediaVideoItem.getVideoProfile());
- assertEquals("Video Level ",
- videoLevel, mediaVideoItem.getVideoLevel());
- assertEquals("Video height ",
- height, mediaVideoItem.getHeight());
- assertEquals("Video width ",
- width, mediaVideoItem.getWidth());
- } catch (Exception e1) {
- assertTrue("Can not create Video Item with file name = "
- + e1.toString(), false);
- }
- }
- timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS*10));
- loggingInfo[0] = "Time taken to get Media Properties :"
- + timeTaken;
- writeTimingInfo("testPerformanceVideoItemProperties:", loggingInfo);
- }
-
- /**
- * To test the performance of generatePreview : with Transitions
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceGeneratePreviewWithTransitions()
- throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String imageItemFileName = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
- long averageTime = 0;
- final String[] loggingInfo = new String[1];
-
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName, renderingMode);
- mediaVideoItem.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
- "mediaItem2", imageItemFileName, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
- "transitionCrossFade", mediaVideoItem, mediaImageItem,
- 5000, transitionBehavior);
- mVideoEditor.addTransition(transitionCrossFade);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final long duration2 = SystemClock.uptimeMillis();
- mVideoEditor.removeTransition(transitionCrossFade.getId());
- mVideoEditor.addTransition(transitionCrossFade);
- averageTime += (duration2 - duration1);
- }
- final long durationToAddObjects = averageTime;
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] = "Time taken to Generate Preview with transition :"
- + timeTaken;
- writeTimingInfo("testPerformanceGeneratePreviewWithTransitions:",
- loggingInfo);
- }
-
- /**
- * To test the performance of generatePreview : with KenBurn
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceWithKenBurn() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String imageItemFileName = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- long averageTime = 0;
- final String[] loggingInfo = new String[1];
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName, renderingMode);
- mediaVideoItem.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
- "mediaItem2", imageItemFileName, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaImageItem);
-
- final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
- (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
- (mediaImageItem.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
- mediaImageItem.getHeight());
- final EffectKenBurns kbEffectOnMediaItem =
- new EffectKenBurns(mediaImageItem, "KBOnM2", startRect, endRect,
- 500, 3000);
- mediaImageItem.addEffect(kbEffectOnMediaItem);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final long duration2 = SystemClock.uptimeMillis();
- mediaImageItem.removeEffect(kbEffectOnMediaItem.getId());
- mediaImageItem.addEffect(kbEffectOnMediaItem);
- averageTime += duration2 - duration1;
- }
-
- final long durationToAddObjects = (averageTime);
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] = "Time taken to Generate KenBurn Effect :"
- + timeTaken;
- writeTimingInfo("testPerformanceWithKenBurn", loggingInfo);
- }
-
- /**
- * To test the performance of generatePreview : with Transitions and
- * Effect,Overlapping scenario
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceEffectOverlappingTransition() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int videoStartTime1 = 0;
- final int videoEndTime1 = 10000;
- final int videoStartTime2 = 0;
- final int videoEndTime2 = 10000;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int transitionDuration = 5000;
- final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
- final int effectItemStartTime = 5000;
- final int effectItemDurationTime = 5000;
- final int effectType = EffectColor.TYPE_COLOR;
- final int effectColorType = EffectColor.GREEN;
- long averageDuration = 0;
-
- final String[] loggingInfo = new String[1];
- final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName1, renderingMode);
- mediaVideoItem1.setExtractBoundaries(videoStartTime1, videoEndTime1);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
- "mediaItem2", videoItemFileName2, renderingMode);
- mediaVideoItem2.setExtractBoundaries(videoStartTime2, videoEndTime2);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
- "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
- transitionDuration, transitionBehavior);
- mVideoEditor.addTransition(transitionCrossFade);
-
- final EffectColor effectColor = new EffectColor(mediaVideoItem1,
- "effect", effectItemStartTime, effectItemDurationTime, effectType,
- effectColorType);
- mediaVideoItem1.addEffect(effectColor);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final long duration2 = SystemClock.uptimeMillis();
- mVideoEditor.removeTransition(transitionCrossFade.getId());
- mVideoEditor.addTransition(transitionCrossFade);
- averageDuration += (duration2 - duration1);
- }
- SystemClock.uptimeMillis();
- final long durationToAddObjects = (averageDuration);
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] =
- "Time taken to testPerformanceEffectOverlappingTransition :"
- + timeTaken;
- writeTimingInfo("testPerformanceEffectOverlappingTransition:",
- loggingInfo);
- }
-
- /**
- * To test creation of story board with Transition and Two Effects, Effect
- * overlapping transitions
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceTransitionWithEffectOverlapping() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH
- + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int transitionDuration = 5000;
- final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
- final int effectItemStartTime1 = 5000;
- final int effectItemDurationTime1 = 5000;
- final int effectType1 = EffectColor.TYPE_COLOR;
- final int effectColorType1 = EffectColor.GREEN;
- final int effectItemStartTime2 = 5000;
- final int effectItemDurationTime2 = 5000;
- final int effectType2 = EffectColor.TYPE_COLOR;
- final int effectColorType2 = EffectColor.GREEN;
- int averageTime = 0;
- final String[] loggingInfo = new String[1];
-
- final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem1);
-
- final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
- "mediaItem2", videoItemFileName2, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem2);
-
- final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
- "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
- transitionDuration, transitionBehavior);
- mVideoEditor.addTransition(transitionCrossFade);
-
- final EffectColor effectColor1 = new EffectColor(mediaVideoItem1,
- "effect1", effectItemStartTime1, effectItemDurationTime1,
- effectType1, effectColorType1);
- mediaVideoItem1.addEffect(effectColor1);
-
- final EffectColor effectColor2 = new EffectColor(mediaVideoItem2,
- "effect2", effectItemStartTime2, effectItemDurationTime2,
- effectType2, effectColorType2);
- mediaVideoItem2.addEffect(effectColor2);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- final long duration2 = SystemClock.uptimeMillis();
- mVideoEditor.removeTransition(transitionCrossFade.getId());
- mVideoEditor.addTransition(transitionCrossFade);
- averageTime += duration2 - duration1;
- }
- final long durationToAddObjects = (averageTime);
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] = "Time taken to TransitionWithEffectOverlapping :"
- + timeTaken;
- writeTimingInfo("testPerformanceTransitionWithEffectOverlapping",
- loggingInfo);
- }
-
- /**
- *To test ThumbnailList for H264
- */
- @LargeTest
- public void testThumbnailH264NonIFrame() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int outWidth = 1080;
- final int outHeight = 720;
- final int atTime = 2400;
- long durationToAddObjects = 0;
- int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[1];
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFilename, renderingMode);
- assertNotNull("MediaVideoItem", mediaVideoItem);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
- final long duration2 = SystemClock.uptimeMillis();
- durationToAddObjects += (duration2 - duration1);
- }
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] = "Time taken for Thumbnail generation :"
- + timeTaken;
- writeTimingInfo("testThumbnailH264NonIFrame", loggingInfo);
- }
-
- /**
- *To test ThumbnailList for H264
- */
- @LargeTest
- public void testThumbnailH264AnIFrame() throws Exception {
- final String videoItemFilename = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final int outWidth = 1080;
- final int outHeight = 720;
- final int atTime = 3000;
- int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[1];
- long durationToAddObjects = 0;
-
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFilename, renderingMode);
- assertNotNull("MediaVideoItem", mediaVideoItem);
-
- for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
- final long duration1 = SystemClock.uptimeMillis();
- mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
- final long duration2 = SystemClock.uptimeMillis();
- durationToAddObjects += (duration2 - duration1);
- }
- final float timeTaken = (float)durationToAddObjects *
- 1.0f/(float)NUM_OF_ITERATIONS;
- loggingInfo[0] = "Time taken Thumbnail generation :"
- + timeTaken;
- writeTimingInfo("testThumbnailH264AnIFrame", loggingInfo);
- }
-
- /**
- * To test the performance : With an audio track
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceWithAudioTrack() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String audioFilename1 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- final String audioFilename2 = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int audioVolume = 50;
- final String[] loggingInfo = new String[2];
- int timeTaken = 0;
-
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
- "Audio Track1", audioFilename1);
- audioTrack1.disableDucking();
- audioTrack1.setVolume(audioVolume);
- mVideoEditor.addAudioTrack(audioTrack1);
-
- long beginTime = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- timeTaken = calculateTimeTaken(beginTime, 1);
- loggingInfo[0] = "Time taken for 1st Audio Track (AACLC) :"
- + timeTaken;
-
- final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
- "Audio Track2", audioFilename2);
- audioTrack2.enableLoop();
-
- beginTime = SystemClock.uptimeMillis();
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- timeTaken = calculateTimeTaken(beginTime, 1);
- loggingInfo[1] = "\n\tTime taken for 2nd Audio Track(AMRNB) :"
- + timeTaken;
-
- writeTimingInfo("testPerformanceWithAudioTrack", loggingInfo);
- }
-
- /**
- * To test the performance of adding and removing the
- * image media item with 640 x 480
- *
- * @throws Exception
- */
- @LargeTest
- public void testPerformanceAddRemoveImageItem640x480() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int imageItemDuration = 0;
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[3];
-
- int timeTaken = 0;
-
- final MediaImageItem[] mediaImageItem =
- new MediaImageItem[NUM_OF_ITERATIONS];
- long beginTime = SystemClock.uptimeMillis();
- createImageItems(mediaImageItem, imageItemFileName, renderingMode,
- imageItemDuration);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[0] = "Time taken to Create Media Image Item (640x480) :"
- + timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- addImageItems(mediaImageItem);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[1] = "\n\tTime taken to add Media Image Item (640x480) :"
- + timeTaken;
-
- beginTime = SystemClock.uptimeMillis();
- removeImageItems(mediaImageItem);
- timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
- loggingInfo[2] = "\n\tTime taken to remove Media Image Item (640x480) :"
- + timeTaken;
- writeTimingInfo("testPerformanceAddRemoveImageItem640x480 (in mSec)", loggingInfo);
- }
-
-
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
deleted file mode 100644
index 7784c7b..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
+++ /dev/null
@@ -1,1309 +0,0 @@
-/*
- * Copyright (C) 2011 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.mediaframeworktest.stress;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.Writer;
-import java.util.List;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditorFactory;
-import android.media.videoeditor.ExtractAudioWaveformProgressListener;
-
-import android.os.Debug;
-import android.util.Log;
-import com.android.mediaframeworktest.MediaFrameworkPerfTestRunner;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-import com.android.mediaframeworktest.MediaTestUtil;
-
-/**
- * Junit / Instrumentation - performance measurement for media player and
- * recorder
- */
-public class VideoEditorStressTest
- extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
-
- private final String TAG = "VideoEditorStressTest";
-
- private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
- private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
- private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
- "VideoEditorStressMemOutput.txt";
-
- private long BeginJavaMemory;
- private long AfterJavaMemory;
-
- private long BeginNativeMemory;
- private long AfterNativeMemory;
-
- public VideoEditorStressTest() {
- super("com.android.mediaframeworktest", MediaFrameworkTest.class);
- new File(VIDEOEDITOR_OUTPUT).delete();
- }
-
- private final String PROJECT_CLASS_NAME =
- "android.media.videoeditor.VideoEditorImpl";
- private VideoEditor mVideoEditor;
- private MediaTestUtil mMediaTestUtil;
- private VideoEditorHelper mVideoEditorHelper;
-
- @Override
- protected void setUp() throws Exception {
- // setup for each test case.
- super.setUp();
- getActivity();
- mMediaTestUtil = new MediaTestUtil(
- "/sdcard/VideoEditorMediaServerMemoryLog.txt",
- this.getName(), "mediaserver");
- mVideoEditorHelper = new VideoEditorHelper();
- // Create a random String which will be used as project path, where all
- // project related files will be stored.
- final String projectPath =
- mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
- mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
- }
-
- @Override
- protected void tearDown() throws Exception {
- final String[] loggingInfo = new String[1];
- mMediaTestUtil.getMemorySummary();
- loggingInfo[0] = "\n" +this.getName();
- writeTimingInfo(loggingInfo);
- loggingInfo[0] = " diff : " + (AfterNativeMemory - BeginNativeMemory);
- writeTimingInfo(loggingInfo);
- mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
- // Clean the directory created as project path
- mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
- System.gc();
- super.tearDown();
- }
-
- private void writeTimingInfo(String[] information)
- throws Exception {
- File outFile = new File(VIDEOEDITOR_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(outFile, true));
- for (int i = 0; i < information.length; i++) {
- output.write(information[i]);
- }
- output.close();
- }
-
- private void writeTestCaseHeader(String testCaseName)
- throws Exception {
- File outFile = new File(VIDEOEDITOR_OUTPUT);
- Writer output = new BufferedWriter(new FileWriter(outFile, true));
- output.write("\n\n" + testCaseName + "\n");
- output.close();
- }
-
- private void getBeginMemory() throws Exception {
- System.gc();
- Thread.sleep(2500);
- BeginNativeMemory = Debug.getNativeHeapAllocatedSize();
- mMediaTestUtil.getStartMemoryLog();
- }
- private void getAfterMemory_updateLog(String[] loggingInfo, boolean when,
- int iteration)
- throws Exception {
- System.gc();
- Thread.sleep(2500);
- AfterNativeMemory = Debug.getNativeHeapAllocatedSize();
- if(when == false){
- loggingInfo[0] = "\n Before Remove: iteration No.= " + iteration +
- "\t " + (AfterNativeMemory - BeginNativeMemory);
- } else {
- loggingInfo[0] = "\n After Remove: iteration No.= " + iteration +
- "\t " + (AfterNativeMemory - BeginNativeMemory);
- }
- writeTimingInfo(loggingInfo);
- mMediaTestUtil.getMemoryLog();
- }
-
- /**
- * To stress test MediaItem(Video Item) adding functionality
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAddRemoveVideoItem() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
- final String videoItemFileName3 = INPUT_FILE_PATH +
- "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
- final String videoItemFileName4 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String[] loggingInfo = new String[1];
- writeTestCaseHeader("testStressAddRemoveVideoItem");
- int i = 0;
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1" + i, videoItemFileName1, renderingMode);
- mediaItem1.setExtractBoundaries(0, 5000);
- mVideoEditor.addMediaItem(mediaItem1);
- }
- if (i % 4 == 1) {
- final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
- "m2" + i, videoItemFileName2, renderingMode);
- mediaItem2.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaItem2);
- }
- if (i % 4 == 2) {
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3" + i, videoItemFileName3, renderingMode);
- mediaItem3.setExtractBoundaries(30000, 45000);
- mVideoEditor.addMediaItem(mediaItem3);
- }
- if (i % 4 == 3) {
- final MediaVideoItem mediaItem4 = new MediaVideoItem(mVideoEditor,
- "m4" + i, videoItemFileName4, renderingMode);
- mediaItem4.setExtractBoundaries(10000, 30000);
- mVideoEditor.addMediaItem(mediaItem4);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- mVideoEditor.removeMediaItem("m1" + i);
- }
- if (i % 4 == 1) {
- mVideoEditor.removeMediaItem("m2" + i);
- }
- if (i % 4 == 2) {
- mVideoEditor.removeMediaItem("m3" + i);
- }
- if (i % 4 == 3) {
- mVideoEditor.removeMediaItem("m4" + i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test MediaItem(Image Item) adding functionality
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAddRemoveImageItem() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String ImageItemFileName1 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String ImageItemFileName3 = INPUT_FILE_PATH +
- "IMG_320x240.jpg";
- final String ImageItemFileName4 = INPUT_FILE_PATH +
- "IMG_176x144.jpg";
- final String[] loggingInfo = new String[1];
- int i = 0;
- writeTestCaseHeader("testStressAddRemoveImageItem");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- final MediaImageItem mediaItem1 = new MediaImageItem(mVideoEditor,
- "m1"+ i, ImageItemFileName1, 5000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- }
- if (i % 4 == 1) {
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2"+ i, ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
- }
- if (i % 4 == 2) {
- final MediaImageItem mediaItem3 = new MediaImageItem(mVideoEditor,
- "m3"+ i, ImageItemFileName3, 15000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem3);
- }
- if (i % 4 == 3) {
- final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
- "m4"+ i, ImageItemFileName4, 20000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem4);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- mVideoEditor.removeMediaItem("m1"+i);
- }
- if (i % 4 == 1) {
- mVideoEditor.removeMediaItem("m2"+i);
- }
- if (i % 4 == 2) {
- mVideoEditor.removeMediaItem("m3"+i);
- }
- if (i % 4 == 3) {
- mVideoEditor.removeMediaItem("m4"+i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test transition
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAddRemoveTransition() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_1_17.mp4";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String VideoItemFileName3 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final String maskFilename = INPUT_FILE_PATH +
- "TransitionSpiral_QVGA.jpg";
- final String[] loggingInfo = new String[1];
- int i = 0;
- writeTestCaseHeader("testStressAddRemoveTransition");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1"+i, VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
- final TransitionCrossfade tranCrossfade =
- new TransitionCrossfade("transCF" + i, null,
- mediaItem1, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(tranCrossfade);
- }
- if (i % 4 == 1) {
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1"+i, VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
-
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2" +i, ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final TransitionAlpha transitionAlpha =
- mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem1,
- mediaItem2, 5000, Transition.BEHAVIOR_SPEED_UP,
- maskFilename, 10, false);
- transitionAlpha.setDuration(4000);
- mVideoEditor.addTransition(transitionAlpha);
- }
- if (i % 4 == 2) {
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2" + i, ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3" + i, VideoItemFileName3, renderingMode);
- mVideoEditor.addMediaItem(mediaItem3);
-
- mediaItem3.setExtractBoundaries(0, 10000);
- final TransitionAlpha transitionAlpha =
- mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem2,
- mediaItem3, 5000, Transition.BEHAVIOR_SPEED_UP,
- maskFilename, 10, false);
- transitionAlpha.setDuration(4000);
- mVideoEditor.addTransition(transitionAlpha);
-
- mediaItem3.setExtractBoundaries(0, 6000);
-
- final TransitionSliding transition2And3 =
- mVideoEditorHelper.createTSliding("transSlide" +i, mediaItem2,
- mediaItem3, 3000, Transition.BEHAVIOR_MIDDLE_FAST,
- TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
- mVideoEditor.addTransition(transition2And3);
- }
- if (i % 4 == 3) {
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3" + i, VideoItemFileName3, renderingMode);
- mVideoEditor.addMediaItem(mediaItem3);
- mediaItem3.setExtractBoundaries(0, 5000);
-
- final TransitionFadeBlack transition3 =
- mVideoEditorHelper.createTFadeBlack("transFB" +i, mediaItem3,
- null, 2500, Transition.BEHAVIOR_SPEED_UP);
- transition3.setDuration(500);
- mVideoEditor.addTransition(transition3);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- mVideoEditor.removeTransition("transCF" + i);
- mVideoEditor.removeMediaItem("m1" + i);
- }
- if (i % 4 == 1) {
- mVideoEditor.removeTransition("transAlpha" + i);
- mVideoEditor.removeMediaItem("m1" + i);
- mVideoEditor.removeMediaItem("m2" + i);
- }
- if (i % 4 == 2) {
- mVideoEditor.removeTransition("transSlide" +i);
- mVideoEditor.removeMediaItem("m2" + i);
- mVideoEditor.removeMediaItem("m3" + i);
- }
- if (i % 4 == 3) {
- mVideoEditor.removeMediaItem("m3" + i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test overlay
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAddRemoveOverlay() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String OverlayFile3 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final String OverlayFile4 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay2.png";
- final String[] loggingInfo = new String[1];
- int i = 0;
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2", ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
- writeTestCaseHeader("testStressAddRemoveOverlay");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 3 == 0) {
- mediaItem1.setExtractBoundaries(0, 10000);
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(
- OverlayFile3, 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
- mBitmap, 1000, 5000);
- mediaItem1.addOverlay(overlayFrame);
- mediaItem1.removeOverlay("overlay"+i);
- }
- if (i % 3 == 1) {
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(
- OverlayFile4, 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem2, "overlay" + i,
- mBitmap, 1000, 5000);
- mediaItem2.addOverlay(overlayFrame);
- mediaItem2.removeOverlay("overlay"+i);
- }
- if (i % 3 == 2) {
- mediaItem1.setExtractBoundaries(0, 10000);
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(
- OverlayFile4, 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
- mBitmap, 0, mediaItem1.getDuration());
- mediaItem1.addOverlay(overlayFrame);
- mediaItem1.removeOverlay("overlay"+i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
-
- /**
- * To stress test Effects
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAddRemoveEffects() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String[] loggingInfo = new String[1];
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2", ImageItemFileName2, 10000, renderingMode);
- int i = 0;
- mVideoEditor.addMediaItem(mediaItem2);
- writeTestCaseHeader("testStressAddRemoveEffects");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 5 == 0) {
- mediaItem1.setExtractBoundaries(10000, 30000);
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
- 10000, (mediaItem1.getTimelineDuration()-1000),
- EffectColor.TYPE_COLOR, EffectColor.GREEN);
- mediaItem1.addEffect(effectColor1);
- }
- if (i % 5 == 1) {
- mediaItem2.setDuration(20000);
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
- 0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
- mediaItem2.addEffect(effectColor1);
- }
- if (i % 5 == 2) {
- mediaItem1.setExtractBoundaries(10000, 30000);
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
- (mediaItem1.getTimelineDuration() - 4000), 4000,
- EffectColor.TYPE_SEPIA, 0);
- mediaItem1.addEffect(effectColor1);
- }
- if (i % 5 == 3) {
- mediaItem2.setDuration(20000);
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
- 10000, 4000, EffectColor.TYPE_NEGATIVE, 0);
- mediaItem2.addEffect(effectColor1);
- }
- if (i % 5 == 4) {
- mediaItem2.setDuration(20000);
- final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
- (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
- (mediaItem2.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
- mediaItem2.getHeight());
- final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
- mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
- (mediaItem2.getDuration() - 500));
- mediaItem2.addEffect(kbEffectOnMediaItem);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 50; i++) {
- if (i % 5 == 0) {
- mediaItem1.removeEffect("effect1"+i);
- }
- if (i % 5 == 1) {
- mediaItem1.removeEffect("effect1"+i);
- }
- if (i % 5 == 2) {
- mediaItem1.removeEffect("effect1"+i);
- }
- if (i % 5 == 3) {
- mediaItem1.removeEffect("effect1"+i);
- }
- if (i % 5 == 4) {
- mediaItem1.removeEffect("KBOnM2"+i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * This method will test thumbnail list extraction in a loop = 200 for Video
- * Item
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressThumbnailVideoItem() throws Exception {
- final String videoItemFileName = INPUT_FILE_PATH
- + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[1];
- int i = 0;
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFileName, renderingMode);
- writeTestCaseHeader("testStressThumbnailVideoItem");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- final Bitmap[] thumbNails =
- mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*3,
- mediaVideoItem.getHeight()/2, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 1) {
- final Bitmap[] thumbNails =
- mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()/2,
- mediaVideoItem.getHeight() * 3, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 2) {
- final Bitmap[] thumbNails =
- mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*2,
- mediaVideoItem.getHeight() / 3, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 3) {
- final Bitmap[] thumbNails =
- mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth(),
- mediaVideoItem.getHeight(), i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
-
- /**
- * To stress test media properties
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressMediaProperties() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String AudioItemFileName3 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- final String[] loggingInfo = new String[1];
- int i = 0;
- final int videoAspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- final int videoFileType = MediaProperties.FILE_MP4;
- final int videoCodecType = MediaProperties.VCODEC_H264;
- final int videoDuration = 77366;
- final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
- final int videoLevel = MediaProperties.H264Level.H264Level13;
- final int videoHeight = MediaProperties.HEIGHT_720;
- final int videoWidth = 1080;
-
- final int imageAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
- final int imageFileType = MediaProperties.FILE_JPEG;
- final int imageWidth = 640;
- final int imageHeight = MediaProperties.HEIGHT_480;
-
- final int audioDuration = 77554;
- final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
- final int audioSamplingFrequency = 44100;
- final int audioChannel = 2;
- writeTestCaseHeader("testStressMediaProperties");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 3 == 0) {
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1" + i, VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 20000);
- assertEquals("Aspect Ratio Mismatch",
- videoAspectRatio, mediaItem1.getAspectRatio());
- assertEquals("File Type Mismatch",
- videoFileType, mediaItem1.getFileType());
- assertEquals("VideoCodec Mismatch",
- videoCodecType, mediaItem1.getVideoType());
- assertEquals("duration Mismatch",
- videoDuration, mediaItem1.getDuration());
- assertEquals("Video Profile ",
- videoProfile, mediaItem1.getVideoProfile());
- assertEquals("Video Level ",
- videoLevel, mediaItem1.getVideoLevel());
- assertEquals("Video height ",
- videoHeight, mediaItem1.getHeight());
- assertEquals("Video width ",
- videoWidth, mediaItem1.getWidth());
- mVideoEditor.removeMediaItem("m1" + i);
- }
- if (i % 3 == 1) {
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2" + i, ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
- assertEquals("Aspect Ratio Mismatch",
- imageAspectRatio, mediaItem2.getAspectRatio());
- assertEquals("File Type Mismatch",
- imageFileType, mediaItem2.getFileType());
- assertEquals("Image height",
- imageHeight, mediaItem2.getHeight());
- assertEquals("Image width",
- imageWidth, mediaItem2.getWidth());
- mVideoEditor.removeMediaItem("m2" + i);
- }
- if (i % 3 == 2) {
- final AudioTrack mediaItem3 = new AudioTrack(mVideoEditor,
- "m3" + i, AudioItemFileName3);
- mVideoEditor.addAudioTrack(mediaItem3);
- assertEquals("AudioType Mismatch", audioCodecType,
- mediaItem3.getAudioType());
- assertEquals("Audio Sampling", audioSamplingFrequency,
- mediaItem3.getAudioSamplingFrequency());
- assertEquals("Audio Channels",
- audioChannel, mediaItem3.getAudioChannels());
- assertEquals("duration Mismatch", audioDuration,
- mediaItem3.getDuration());
- mVideoEditor.removeAudioTrack("m3" + i);
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
-
- /**
- * To stress test insert and move of mediaitems
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressInsertMovieItems() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String VideoItemFileName2 = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_1_17.mp4";
- final String VideoItemFileName3 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String[] loggingInfo = new String[1];
- int i = 0;
- writeTestCaseHeader("testStressInsertMovieItems");
-
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
-
- final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
- "m2", VideoItemFileName2, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
- mediaItem2.setExtractBoundaries(0, 15000);
-
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3" + i, VideoItemFileName3, renderingMode);
- mediaItem3.setExtractBoundaries(0, 15000);
- mVideoEditor.insertMediaItem(mediaItem3, "m1");
- mVideoEditor.moveMediaItem("m2", "m3" + i);
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 50; i++) {
- mVideoEditor.removeMediaItem("m3" + i);
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- }
- mVideoEditor.removeMediaItem("m2");
- mVideoEditor.removeMediaItem("m1");
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test : load and save
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressLoadAndSave() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String VideoItemFileName2 = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_1_17.mp4";
- final String VideoItemFileName3 = INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
- final String ImageItemFileName4 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String ImageItemFileName5 = INPUT_FILE_PATH +
- "IMG_176x144.jpg";
- final String OverlayFile6 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final String[] loggingInfo = new String[1];
- int i = 0;
- final String[] projectPath = new String[10];
- writeTestCaseHeader("testStressLoadAndSave");
- getBeginMemory();
- for( i=0; i < 10; i++){
-
- projectPath[i] =
- mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
- final VideoEditor mVideoEditor1 =
- mVideoEditorHelper.createVideoEditor(projectPath[i]);
-
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor1,
- "m1", VideoItemFileName1, renderingMode);
- mVideoEditor1.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
-
- final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor1,
- "m2", VideoItemFileName2, renderingMode);
- mVideoEditor1.addMediaItem(mediaItem2);
- mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
- mediaItem2.getDuration()/2);
-
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor1,
- "m3", VideoItemFileName3, renderingMode);
- mVideoEditor1.addMediaItem(mediaItem3);
- mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
- mediaItem3.getDuration());
-
- final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor1,
- "m4", ImageItemFileName4, 5000, renderingMode);
- mVideoEditor1.addMediaItem(mediaItem4);
-
- final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor1,
- "m5", ImageItemFileName5, 5000, renderingMode);
- mVideoEditor1.addMediaItem(mediaItem5);
-
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem3, "effect1",
- 10000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
- mediaItem3.addEffect(effectColor1);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(OverlayFile6,
- 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem4, "overlay",
- mBitmap, 4000, 1000);
- mediaItem4.addOverlay(overlayFrame);
-
- final TransitionCrossfade tranCrossfade =
- new TransitionCrossfade("transCF", mediaItem1,
- mediaItem2, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor1.addTransition(tranCrossfade);
-
- final EffectColor effectColor2 =
- mVideoEditorHelper.createEffectItem(mediaItem4, "effect2", 0,
- mediaItem4.getDuration(), EffectColor.TYPE_COLOR,
- EffectColor.PINK);
- mediaItem4.addEffect(effectColor2);
-
- mVideoEditor1.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- mVideoEditor1.save();
- mVideoEditor1.release();
-
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for( i=0; i<10; i++){
- final VideoEditor mVideoEditor1b =
- VideoEditorFactory.load(projectPath[i], true);
- List<MediaItem> mediaList = mVideoEditor1b.getAllMediaItems();
- assertEquals("Media Item List Size", 5, mediaList.size());
-
- mediaList.get(3).removeEffect("effect1");
- mediaList.get(3).removeEffect("effect2");
- mediaList.get(2).removeOverlay("overlay");
- mVideoEditor1b.removeTransition("transCF");
- mVideoEditor1b.removeMediaItem("m5");
- mVideoEditor1b.removeMediaItem("m4");
- mVideoEditor1b.removeMediaItem("m3");
- mVideoEditor1b.removeMediaItem("m2");
- mVideoEditor1b.removeMediaItem("m1");
- mVideoEditor1b.release();
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test : Multiple Export
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressMultipleExport() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String VideoItemFileName2 = INPUT_FILE_PATH +
- "H264_BP_800x480_15fps_512kbps_1_17.mp4";
- final String[] loggingInfo = new String[1];
- final String outFilename = mVideoEditorHelper.createRandomFile(
- mVideoEditor.getPath() + "/") + ".3gp";
- int i = 0;
- writeTestCaseHeader("testStressMultipleExport");
- getBeginMemory();
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
-
- final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
- "m2", VideoItemFileName2, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
- mediaItem2.setExtractBoundaries(0, 15000);
-
- for ( i = 0; i < 50; i++) {
- if(i%4 ==0){
- final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
- mVideoEditor.setAspectRatio(aspectRatio);
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_288,
- MediaProperties.BITRATE_256K,MediaProperties.ACODEC_AAC_LC,
- MediaProperties.VCODEC_H263,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- }
- });
- }
- if(i%4 ==1){
- final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
- mVideoEditor.setAspectRatio(aspectRatio);
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
- MediaProperties.BITRATE_384K,MediaProperties.ACODEC_AAC_LC,
- MediaProperties.VCODEC_MPEG4,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- }
- });
- }
- if(i%4 ==2){
- final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
- mVideoEditor.setAspectRatio(aspectRatio);
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
- MediaProperties.BITRATE_512K,MediaProperties.ACODEC_AAC_LC,
- MediaProperties.VCODEC_H264,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- }
- });
- }
- if(i%4 ==3){
- final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
- mVideoEditor.setAspectRatio(aspectRatio);
- mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480,
- MediaProperties.BITRATE_800K,MediaProperties.ACODEC_AAC_LC,
- MediaProperties.VCODEC_H264,
- new ExportProgressListener() {
- public void onProgress(VideoEditor ve, String outFileName,
- int progress) {
- }
- });
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- mVideoEditor.removeMediaItem("m2");
- mVideoEditor.removeMediaItem("m1");
-
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To stress test Media Item,Overlays,Transitions and Ken Burn
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressOverlayTransKenBurn() throws Exception {
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String VideoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_640x480_30fps_256kbps_1_17.mp4";
- final String ImageItemFileName2 = INPUT_FILE_PATH +
- "IMG_640x480.jpg";
- final String OverlayFile3 = INPUT_FILE_PATH +
- "IMG_640x480_Overlay1.png";
- final String audioFilename4 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- int i = 0;
- final String[] loggingInfo = new String[1];
- writeTestCaseHeader("testStressOverlayTransKenBurn");
- getBeginMemory();
- for ( i = 0; i < 10; i++) {
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1" + i, VideoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaItem1);
- mediaItem1.setExtractBoundaries(0, 10000);
-
- final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
- "m2" + i, ImageItemFileName2, 10000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final EffectColor effectColor1 =
- mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
- (mediaItem1.getDuration() - 4000), 4000,
- EffectColor.TYPE_SEPIA, 0);
- mediaItem1.addEffect(effectColor1);
-
- final TransitionCrossfade tranCrossfade =
- new TransitionCrossfade("transCF" + i, mediaItem1,
- mediaItem2, 4000, Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(tranCrossfade);
-
- final Bitmap mBitmap = mVideoEditorHelper.getBitmap(OverlayFile3,
- 640, 480);
- final OverlayFrame overlayFrame =
- mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
- mBitmap, 1000, 5000);
- mediaItem1.addOverlay(overlayFrame);
-
- final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
- (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
- (mediaItem2.getWidth() / 2));
- final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
- mediaItem2.getHeight());
-
- final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
- mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
- (mediaItem2.getDuration()-500));
- mediaItem2.addEffect(kbEffectOnMediaItem);
-
- if(i == 5) {
- final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
- "Audio Track1", audioFilename4);
- mVideoEditor.addAudioTrack(audioTrack1);
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- for ( i = 0; i < 10; i++) {
- MediaImageItem m2 = (MediaImageItem)mVideoEditor.getMediaItem("m2"+i);
- MediaVideoItem m1 = (MediaVideoItem)mVideoEditor.getMediaItem("m1"+i);
- m2.removeEffect("KBOnM2" + i);
- m1.removeOverlay("overlay" + i);
- mVideoEditor.removeTransition("transCF" + i);
- m1.removeEffect("effect1" + i);
- mVideoEditor.removeMediaItem("m2" + i);
- mVideoEditor.removeMediaItem("m1" + i);
- if(i == 5) {
- mVideoEditor.removeAudioTrack("Audio Track1");
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To test the performance : With an audio track with Video
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAudioTrackVideo() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
- final String audioFilename1 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- final String audioFilename2 = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int audioVolume = 50;
- final String[] loggingInfo = new String[1];
- int i = 1;
- writeTestCaseHeader("testStressAudioTrackVideo");
- getBeginMemory();
- final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
- "mediaItem1", videoItemFileName1, renderingMode);
- mVideoEditor.addMediaItem(mediaVideoItem);
-
- final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
- "Audio Track1", audioFilename1);
- audioTrack1.disableDucking();
- audioTrack1.setVolume(audioVolume);
- mVideoEditor.addAudioTrack(audioTrack1);
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
-
- mVideoEditor.removeAudioTrack("Audio Track1");
-
- final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
- "Audio Track2", audioFilename2);
- audioTrack2.enableLoop();
-
- mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
- public void onProgress(Object item, int action, int progress) {
- }
- });
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- mVideoEditor.removeMediaItem("mediaItem1");
-
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To Test Stress : Story Board creation with out preview or export
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressStoryBoard() throws Exception {
- final String videoItemFileName1 = INPUT_FILE_PATH +
- "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
- final String videoItemFileName2 = INPUT_FILE_PATH +
- "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
- final String videoItemFileName3= INPUT_FILE_PATH +
- "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
- final String imageItemFileName4 = INPUT_FILE_PATH +
- "IMG_1600x1200.jpg";
- final String imageItemFileName5 = INPUT_FILE_PATH +
- "IMG_176x144.jpg";
- final String audioFilename6 = INPUT_FILE_PATH +
- "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
- final String audioFilename7 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final int audioVolume = 50;
- final String[] loggingInfo = new String[1];
- int i = 1;
-
- writeTestCaseHeader("testStressStoryBoard");
- getBeginMemory();
- final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
- "m1", videoItemFileName1, renderingMode);
- mediaItem1.setExtractBoundaries(0, 10000);
- mVideoEditor.addMediaItem(mediaItem1);
-
- final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
- "m2", videoItemFileName2, renderingMode);
- mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
- mediaItem2.getDuration()/2);
- mVideoEditor.addMediaItem(mediaItem2);
-
- final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
- "m3", videoItemFileName3, renderingMode);
- mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
- mediaItem3.getDuration());
- mVideoEditor.addMediaItem(mediaItem3);
-
- final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
- "m4", imageItemFileName4, 5000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem4);
-
- final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor,
- "m5", imageItemFileName5, 5000, renderingMode);
- mVideoEditor.addMediaItem(mediaItem5);
-
- final TransitionCrossfade tranCrossfade =
- new TransitionCrossfade("transCF", mediaItem2, mediaItem3, 2500,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(tranCrossfade);
-
- final TransitionCrossfade tranCrossfade1 =
- new TransitionCrossfade("transCF1", mediaItem3, mediaItem4, 2500,
- Transition.BEHAVIOR_MIDDLE_FAST);
- mVideoEditor.addTransition(tranCrossfade1);
-
- final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
- "Audio Track1", audioFilename6);
- mVideoEditor.addAudioTrack(audioTrack1);
-
- mVideoEditor.removeAudioTrack("Audio Track1");
- final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
- "Audio Track2", audioFilename7);
- mVideoEditor.addAudioTrack(audioTrack2);
- audioTrack2.enableLoop();
- getAfterMemory_updateLog(loggingInfo, false, i);
-
- /** Remove items and check for memory leak if any */
- getBeginMemory();
- mVideoEditor.removeAudioTrack("Audio Track2");
- mVideoEditor.removeTransition("transCF");
- mVideoEditor.removeTransition("transCF1");
- mVideoEditor.removeMediaItem("m5");
- mVideoEditor.removeMediaItem("m4");
- mVideoEditor.removeMediaItem("m3");
- mVideoEditor.removeMediaItem("m2");
- mVideoEditor.removeMediaItem("m1");
-
- getAfterMemory_updateLog(loggingInfo, true, i);
- }
-
- /**
- * To test the performance : With an audio track Only
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressAudioTrackOnly() throws Exception {
-
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String AudioItemFileName1 = INPUT_FILE_PATH +
- "AACLC_44.1kHz_256kbps_s_1_17.mp4";
- final String[] loggingInfo = new String[1];
- int i = 0;
- writeTestCaseHeader("testStressAudioTrackOnly");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- final AudioTrack mediaItem1 = new AudioTrack(mVideoEditor,
- "m1" + i, AudioItemFileName1);
- mVideoEditor.addAudioTrack(mediaItem1);
- mediaItem1.enableLoop();
- mVideoEditor.removeAudioTrack("m1" + i);
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
-
- /**
- * This method will test thumbnail list extraction in a loop = 200 for Image
- * Item
- *
- * @throws Exception
- */
- @LargeTest
- public void testStressThumbnailImageItem() throws Exception {
- final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
- final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
- final String[] loggingInfo = new String[1];
- int i = 0;
- final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
- "m1", imageItemFileName, 5000, renderingMode);
- writeTestCaseHeader("testStressThumbnailImageItem");
- getBeginMemory();
- for ( i = 0; i < 50; i++) {
- if (i % 4 == 0) {
- final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
- mediaImageItem.getWidth() / 2 ,
- mediaImageItem.getHeight() / 2, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 1) {
- final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
- mediaImageItem.getWidth() / 2,
- mediaImageItem.getHeight() * 3, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 2) {
- final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
- mediaImageItem.getWidth() * 2,
- mediaImageItem.getHeight() / 3, i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 4 == 3) {
- final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
- mediaImageItem.getWidth(),
- mediaImageItem.getHeight(), i, 5000, 2);
- // Recycle this Bitmap array
- for (int i1 = 0; i1 < thumbNails.length; i1++) {
- thumbNails[i1].recycle();
- }
- }
- if (i % 10 == 0) {
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
- }
- getAfterMemory_updateLog(loggingInfo, false, i);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index edfa36a..45df065 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -309,7 +309,7 @@
});
// rational (n) -- in particular rational x 9
- checkKeyGetAndSetArray("android.sensor.calibrationTransform", Rational[].class,
+ checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class,
new Rational[] {
new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index a9322b9..1406f6b 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -878,7 +878,7 @@
protected int[] mConfigSpec;
private int[] filterConfigSpec(int[] configSpec) {
- if (mEGLContextClientVersion != 2) {
+ if (mEGLContextClientVersion != 2 && mEGLContextClientVersion != 3) {
return configSpec;
}
/* We know none of the subclasses define EGL_RENDERABLE_TYPE.
@@ -888,7 +888,11 @@
int[] newConfigSpec = new int[len + 2];
System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
- newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
+ if (mEGLContextClientVersion == 2) {
+ newConfigSpec[len] = EGL14.EGL_OPENGL_ES2_BIT; /* EGL_OPENGL_ES2_BIT */
+ } else {
+ newConfigSpec[len] = EGLExt.EGL_OPENGL_ES3_BIT_KHR; /* EGL_OPENGL_ES3_BIT_KHR */
+ }
newConfigSpec[len+1] = EGL10.EGL_NONE;
return newConfigSpec;
}
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6b77a7c..159ee66 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -9,18 +9,17 @@
android:label="@string/app_label"
android:supportsRtl="true">
- <!-- TODO: allow rotation when state saving is in better shape -->
<activity
android:name=".DocumentsActivity"
android:theme="@style/Theme"
android:icon="@drawable/ic_doc_text">
- <intent-filter android:priority="100">
+ <intent-filter>
<action android:name="android.intent.action.OPEN_DOCUMENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="*/*" />
</intent-filter>
- <intent-filter android:priority="100">
+ <intent-filter>
<action android:name="android.intent.action.CREATE_DOCUMENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
@@ -33,6 +32,10 @@
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter>
+ <action android:name="android.intent.action.PICK_DIRECTORY" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <intent-filter>
<action android:name="android.provider.action.MANAGE_ROOT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.document/root" />
@@ -57,14 +60,5 @@
<data android:scheme="package" />
</intent-filter>
</receiver>
-
- <!-- TODO: remove when we have real clients -->
- <activity android:name=".TestActivity" android:enabled="false">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
</application>
</manifest>
diff --git a/packages/DocumentsUI/res/layout/fragment_pick.xml b/packages/DocumentsUI/res/layout/fragment_pick.xml
new file mode 100644
index 0000000..4a2fd03
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/fragment_pick.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <!-- Le sigh, this really should be an asset -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="#ccc" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:baselineAligned="false"
+ android:gravity="center_vertical"
+ android:background="#ddd"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
+
+ <Button
+ android:id="@android:id/button1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAllCaps="false"
+ android:padding="8dp" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 92c30ba..c1a9d72 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -44,6 +44,8 @@
<string name="menu_share">Share</string>
<!-- Menu item title that deletes the selected documents [CHAR LIMIT=24] -->
<string name="menu_delete">Delete</string>
+ <!-- Menu item title that selects the current directory [CHAR LIMIT=48] -->
+ <string name="menu_select">Select \"<xliff:g id="directory" example="My Directory">^1</xliff:g>\"</string>
<!-- Action mode title summarizing the number of documents selected [CHAR LIMIT=32] -->
<string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 4212e96..9f76991 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -24,6 +24,7 @@
import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
import static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN;
+import static com.android.documentsui.DocumentsActivity.State.ACTION_PICK_DIRECTORY;
import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
@@ -202,6 +203,8 @@
final String mimeType = getIntent().getType();
final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
SaveFragment.show(getFragmentManager(), mimeType, title);
+ } else if (mState.action == ACTION_PICK_DIRECTORY) {
+ PickFragment.show(getFragmentManager());
}
if (mState.action == ACTION_GET_CONTENT) {
@@ -209,7 +212,8 @@
moreApps.setComponent(null);
moreApps.setPackage(null);
RootsFragment.show(getFragmentManager(), moreApps);
- } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE) {
+ } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE
+ || mState.action == ACTION_PICK_DIRECTORY) {
RootsFragment.show(getFragmentManager(), null);
}
@@ -236,6 +240,8 @@
mState.action = ACTION_CREATE;
} else if (Intent.ACTION_GET_CONTENT.equals(action)) {
mState.action = ACTION_GET_CONTENT;
+ } else if (Intent.ACTION_PICK_DIRECTORY.equals(action)) {
+ mState.action = ACTION_PICK_DIRECTORY;
} else if (DocumentsContract.ACTION_MANAGE_ROOT.equals(action)) {
mState.action = ACTION_MANAGE;
}
@@ -434,7 +440,8 @@
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setIcon(new ColorDrawable());
- if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
+ if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT
+ || mState.action == ACTION_PICK_DIRECTORY) {
actionBar.setTitle(R.string.title_open);
} else if (mState.action == ACTION_CREATE) {
actionBar.setTitle(R.string.title_save);
@@ -576,7 +583,7 @@
sortSize.setVisible(mState.showSize);
final boolean searchVisible;
- if (mState.action == ACTION_CREATE) {
+ if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
createDir.setVisible(cwd != null && cwd.isCreateSupported());
searchVisible = false;
@@ -586,7 +593,9 @@
list.setVisible(false);
}
- SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
+ if (mState.action == ACTION_CREATE) {
+ SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
+ }
} else {
createDir.setVisible(false);
@@ -819,7 +828,7 @@
if (cwd == null) {
// No directory means recents
- if (mState.action == ACTION_CREATE) {
+ if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
RecentsCreateFragment.show(fm);
} else {
DirectoryFragment.showRecentsOpen(fm, anim);
@@ -848,6 +857,15 @@
}
}
+ if (mState.action == ACTION_PICK_DIRECTORY) {
+ final PickFragment pick = PickFragment.get(fm);
+ if (pick != null) {
+ final CharSequence displayName = (mState.stack.size() <= 1) ? root.title
+ : cwd.displayName;
+ pick.setPickTarget(cwd, displayName);
+ }
+ }
+
final RootsFragment roots = RootsFragment.get(fm);
if (roots != null) {
roots.onCurrentRootChanged();
@@ -1002,12 +1020,18 @@
new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
}
+ public void onPickRequested(DocumentInfo pickTarget) {
+ final Uri viaUri = DocumentsContract.buildViaUri(pickTarget.authority,
+ pickTarget.documentId);
+ new PickFinishTask(viaUri).executeOnExecutor(getCurrentExecutor());
+ }
+
private void saveStackBlocking() {
final ContentResolver resolver = getContentResolver();
final ContentValues values = new ContentValues();
final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
- if (mState.action == ACTION_CREATE) {
+ if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
// Remember stack for last create
values.clear();
values.put(RecentColumns.KEY, mState.stack.buildKey());
@@ -1040,6 +1064,11 @@
if (mState.action == ACTION_GET_CONTENT) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ } else if (mState.action == ACTION_PICK_DIRECTORY) {
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
} else {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@@ -1121,6 +1150,25 @@
}
}
+ private class PickFinishTask extends AsyncTask<Void, Void, Void> {
+ private final Uri mUri;
+
+ public PickFinishTask(Uri uri) {
+ mUri = uri;
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ saveStackBlocking();
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ onFinished(mUri);
+ }
+ }
+
public static class State implements android.os.Parcelable {
public int action;
public String[] acceptMimes;
@@ -1154,7 +1202,8 @@
public static final int ACTION_OPEN = 1;
public static final int ACTION_CREATE = 2;
public static final int ACTION_GET_CONTENT = 3;
- public static final int ACTION_MANAGE = 4;
+ public static final int ACTION_PICK_DIRECTORY = 4;
+ public static final int ACTION_MANAGE = 5;
public static final int MODE_UNKNOWN = 0;
public static final int MODE_LIST = 1;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
new file mode 100644
index 0000000..a9e488a1
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 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.documentsui;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.android.documentsui.model.DocumentInfo;
+
+import java.util.Locale;
+
+/**
+ * Display pick confirmation bar, usually for selecting a directory.
+ */
+public class PickFragment extends Fragment {
+ public static final String TAG = "PickFragment";
+
+ private DocumentInfo mPickTarget;
+
+ private View mContainer;
+ private Button mPick;
+
+ public static void show(FragmentManager fm) {
+ final PickFragment fragment = new PickFragment();
+
+ final FragmentTransaction ft = fm.beginTransaction();
+ ft.replace(R.id.container_save, fragment, TAG);
+ ft.commitAllowingStateLoss();
+ }
+
+ public static PickFragment get(FragmentManager fm) {
+ return (PickFragment) fm.findFragmentByTag(TAG);
+ }
+
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ mContainer = inflater.inflate(R.layout.fragment_pick, container, false);
+
+ mPick = (Button) mContainer.findViewById(android.R.id.button1);
+ mPick.setOnClickListener(mPickListener);
+
+ setPickTarget(null, null);
+
+ return mContainer;
+ }
+
+ private View.OnClickListener mPickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final DocumentsActivity activity = DocumentsActivity.get(PickFragment.this);
+ activity.onPickRequested(mPickTarget);
+ }
+ };
+
+ public void setPickTarget(DocumentInfo pickTarget, CharSequence displayName) {
+ mPickTarget = pickTarget;
+
+ if (mPickTarget != null) {
+ mContainer.setVisibility(View.VISIBLE);
+ final Locale locale = getResources().getConfiguration().locale;
+ final String raw = getString(R.string.menu_select).toUpperCase(locale);
+ mPick.setText(TextUtils.expandTemplate(raw, displayName));
+ } else {
+ mContainer.setVisibility(View.GONE);
+ }
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index f1dca1d..933dbe0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -104,7 +104,8 @@
mRecentsRoot.authority = null;
mRecentsRoot.rootId = null;
mRecentsRoot.icon = R.drawable.ic_root_recent;
- mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE;
+ mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE
+ | Root.FLAG_SUPPORTS_DIR_SELECTION;
mRecentsRoot.title = mContext.getString(R.string.root_recent);
mRecentsRoot.availableBytes = -1;
@@ -349,12 +350,15 @@
final List<RootInfo> matching = Lists.newArrayList();
for (RootInfo root : roots) {
final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
+ final boolean supportsDir = (root.flags & Root.FLAG_SUPPORTS_DIR_SELECTION) != 0;
final boolean advanced = (root.flags & Root.FLAG_ADVANCED) != 0;
final boolean localOnly = (root.flags & Root.FLAG_LOCAL_ONLY) != 0;
final boolean empty = (root.flags & Root.FLAG_EMPTY) != 0;
// Exclude read-only devices when creating
if (state.action == State.ACTION_CREATE && !supportsCreate) continue;
+ // Exclude roots that don't support directory picking
+ if (state.action == State.ACTION_PICK_DIRECTORY && !supportsDir) continue;
// Exclude advanced devices when not requested
if (!state.showAdvanced && advanced) continue;
// Exclude non-local devices when local only
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
deleted file mode 100644
index 1a47308..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2013 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.documentsui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class TestActivity extends Activity {
- private static final String TAG = "TestActivity";
-
- private static final int CODE_READ = 42;
- private static final int CODE_WRITE = 43;
-
- private TextView mResult;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final Context context = this;
-
- final LinearLayout view = new LinearLayout(context);
- view.setOrientation(LinearLayout.VERTICAL);
-
- mResult = new TextView(context);
- view.addView(mResult);
-
- final CheckBox multiple = new CheckBox(context);
- multiple.setText("ALLOW_MULTIPLE");
- view.addView(multiple);
- final CheckBox localOnly = new CheckBox(context);
- localOnly.setText("LOCAL_ONLY");
- view.addView(localOnly);
-
- Button button;
- button = new Button(context);
- button.setText("OPEN_DOC */*");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("*/*");
- if (multiple.isChecked()) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_READ);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("OPEN_DOC image/*");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("image/*");
- if (multiple.isChecked()) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_READ);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("OPEN_DOC audio/ogg");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("audio/ogg");
- if (multiple.isChecked()) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_READ);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("OPEN_DOC text/plain, application/msword");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("*/*");
- intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
- "text/plain", "application/msword" });
- if (multiple.isChecked()) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_READ);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("CREATE_DOC text/plain");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("text/plain");
- intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_WRITE);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("CREATE_DOC image/png");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("image/png");
- intent.putExtra(Intent.EXTRA_TITLE, "mypicture.png");
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(intent, CODE_WRITE);
- }
- });
- view.addView(button);
-
- button = new Button(context);
- button.setText("GET_CONTENT */*");
- button.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("*/*");
- if (multiple.isChecked()) {
- intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
- }
- if (localOnly.isChecked()) {
- intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
- }
- startActivityForResult(Intent.createChooser(intent, "Kittens!"), CODE_READ);
- }
- });
- view.addView(button);
-
- final ScrollView scroll = new ScrollView(context);
- scroll.addView(view);
-
- setContentView(scroll);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- mResult.setText(null);
- String result = "resultCode=" + resultCode + ", data=" + String.valueOf(data);
-
- if (requestCode == CODE_READ) {
- final Uri uri = data != null ? data.getData() : null;
- if (uri != null) {
- if (DocumentsContract.isDocumentUri(this, uri)) {
- result += "; DOC_ID";
- }
- try {
- getContentResolver().takePersistableUriPermission(
- uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
- } catch (SecurityException e) {
- result += "; FAILED TO TAKE";
- Log.e(TAG, "Failed to take", e);
- }
- InputStream is = null;
- try {
- is = getContentResolver().openInputStream(uri);
- final int length = Streams.readFullyNoClose(is).length;
- result += "; read length=" + length;
- } catch (Exception e) {
- result += "; ERROR";
- Log.e(TAG, "Failed to read " + uri, e);
- } finally {
- IoUtils.closeQuietly(is);
- }
- } else {
- result += "no uri?";
- }
- } else if (requestCode == CODE_WRITE) {
- final Uri uri = data != null ? data.getData() : null;
- if (uri != null) {
- if (DocumentsContract.isDocumentUri(this, uri)) {
- result += "; DOC_ID";
- }
- try {
- getContentResolver().takePersistableUriPermission(
- uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- } catch (SecurityException e) {
- result += "; FAILED TO TAKE";
- Log.e(TAG, "Failed to take", e);
- }
- OutputStream os = null;
- try {
- os = getContentResolver().openOutputStream(uri);
- os.write("THE COMPLETE WORKS OF SHAKESPEARE".getBytes());
- } catch (Exception e) {
- result += "; ERROR";
- Log.e(TAG, "Failed to write " + uri, e);
- } finally {
- IoUtils.closeQuietly(os);
- }
- } else {
- result += "no uri?";
- }
- }
-
- Log.d(TAG, result);
- mResult.setText(result);
- }
-}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 559e052..16fc3e5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -27,6 +27,7 @@
import android.os.CancellationSignal;
import android.os.Environment;
import android.os.FileObserver;
+import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
@@ -143,7 +144,7 @@
final RootInfo root = new RootInfo();
root.rootId = rootId;
root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
- | Root.FLAG_SUPPORTS_SEARCH;
+ | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_DIR_SELECTION;
if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) {
root.title = getContext().getString(R.string.root_internal_storage);
} else {
@@ -240,8 +241,8 @@
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
} else {
flags |= Document.FLAG_SUPPORTS_WRITE;
+ flags |= Document.FLAG_SUPPORTS_DELETE;
}
- flags |= Document.FLAG_SUPPORTS_DELETE;
}
final String displayName = file.getName();
@@ -284,11 +285,26 @@
}
@Override
+ public boolean isChildDocument(String parentDocId, String docId) {
+ try {
+ final File parent = getFileForDocId(parentDocId).getCanonicalFile();
+ final File doc = getFileForDocId(docId).getCanonicalFile();
+ return FileUtils.contains(parent, doc);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(
+ "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
+ }
+ }
+
+ @Override
public String createDocument(String docId, String mimeType, String displayName)
throws FileNotFoundException {
final File parent = getFileForDocId(docId);
- File file;
+ if (!parent.isDirectory()) {
+ throw new IllegalArgumentException("Parent document isn't a directory");
+ }
+ File file;
if (Document.MIME_TYPE_DIR.equals(mimeType)) {
file = new File(parent, displayName);
if (!file.mkdir()) {
@@ -317,6 +333,7 @@
@Override
public void deleteDocument(String docId) throws FileNotFoundException {
+ // TODO: extend to delete directories
final File file = getFileForDocId(docId);
if (!file.delete()) {
throw new IllegalStateException("Failed to delete " + file);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index d371d70..327df8d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -273,7 +273,8 @@
<service
android:name=".keyguard.KeyguardService"
- android:exported="true" />
+ android:exported="true"
+ android:enabled="@bool/config_enableKeyguardService" />
<activity android:name=".Somnambulator"
android:label="@string/start_dreams"
diff --git a/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..85db9c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..c4941a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..4618f40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png
new file mode 100644
index 0000000..36e7e45
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..c0bf31d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml
index 28d9625..f3c1b90 100644
--- a/packages/SystemUI/res/layout/flip_settings.xml
+++ b/packages/SystemUI/res/layout/flip_settings.xml
@@ -22,4 +22,5 @@
android:layout_height="wrap_content"
android:background="#5f000000"
android:animateLayoutChanges="true"
+ android:visibility="gone"
android:columnCount="@integer/quick_settings_num_columns" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
new file mode 100644
index 0000000..88b01c7
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 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
+ -->
+
+<com.android.systemui.statusbar.phone.KeyguardBottomAreaView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:id="@+id/keyguard_bottom_area"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ >
+ <com.android.systemui.statusbar.policy.KeyButtonView
+ android:id="@+id/camera_button"
+ android:layout_height="80dp"
+ android:layout_width="80dp"
+ android:layout_gravity="bottom|right"
+ android:src="@drawable/ic_sysbar_camera"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_camera_button"
+ systemui:glowBackground="@drawable/ic_sysbar_highlight_land" />
+</com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index a6fb443..2398849 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -159,18 +159,6 @@
android:visibility="gone"
android:contentDescription="@string/accessibility_search_light"
/>
-
- <com.android.systemui.statusbar.policy.KeyButtonView
- android:id="@+id/camera_button"
- android:layout_height="match_parent"
- android:layout_width="80dp"
- android:layout_gravity="center_vertical|right"
- android:src="@drawable/ic_sysbar_camera"
- android:scaleType="center"
- android:visibility="gone"
- android:contentDescription="@string/accessibility_camera_button"
- systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
- />
</FrameLayout>
<com.android.systemui.statusbar.policy.DeadZone
diff --git a/packages/SystemUI/res/layout/quick_settings.xml b/packages/SystemUI/res/layout/quick_settings.xml
deleted file mode 100644
index 75082ba..0000000
--- a/packages/SystemUI/res/layout/quick_settings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.systemui.statusbar.phone.SettingsPanelView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@+id/settings_panel"
- android:background="@drawable/notification_panel_bg"
- >
- <!-- TODO: Put into ScrollView -->
- <com.android.systemui.statusbar.phone.QuickSettingsScrollView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/close_handle_underlap"
- android:overScrollMode="ifContentScrolls"
- >
- <com.android.systemui.statusbar.phone.QuickSettingsContainerView
- android:id="@+id/quick_settings_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:animateLayoutChanges="true"
- android:columnCount="@integer/quick_settings_num_columns"
- />
- </com.android.systemui.statusbar.phone.QuickSettingsScrollView>
-
- <View
- android:id="@+id/handle"
- android:layout_width="match_parent"
- android:layout_height="@dimen/close_handle_height"
- android:background="@drawable/status_bar_close"
- android:visibility="invisible"
- />
-
-</com.android.systemui.statusbar.phone.SettingsPanelView >
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_search_bar.xml b/packages/SystemUI/res/layout/recents_search_bar.xml
new file mode 100644
index 0000000..915283e
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_search_bar.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/search_bg_transparent">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/recents_search_bar_label"
+ android:textColor="#99ffffff"
+ android:textSize="18sp"
+ android:textAllCaps="true" />
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 7f64032..4442bca 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -63,13 +63,6 @@
android:maxLines="2"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
- <ImageView
- android:id="@+id/activity_icon"
- android:layout_width="@dimen/recents_task_view_activity_icon_size"
- android:layout_height="@dimen/recents_task_view_activity_icon_size"
- android:layout_gravity="center_vertical|end"
- android:padding="12dp"
- android:visibility="invisible" />
</com.android.systemui.recents.views.TaskBarView>
</com.android.systemui.recents.views.TaskView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 8a3f090..69fbc1b 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -36,8 +36,9 @@
android:layout_gravity="bottom"
/>
- <ViewStub android:id="@+id/keyguard_flip_stub"
- android:layout="@layout/status_bar_flip_button"
+ <include
+ layout="@layout/status_bar_flip_button"
+ android:id="@+id/keyguard_flipper"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="right|top"
@@ -76,8 +77,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
- <ViewStub android:id="@+id/flip_settings_stub"
- android:layout="@layout/flip_settings"
+ <include
+ layout="@layout/flip_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
@@ -89,4 +90,8 @@
/>
</FrameLayout>
</LinearLayout>
+
+ <include
+ layout="@layout/keyguard_bottom_area"
+ android:visibility="gone" />
</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 56523db..8975728 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -84,6 +84,7 @@
/>
<include layout="@layout/status_bar_flip_button"
+ android:id="@+id/header_flipper"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="12dp" />
diff --git a/packages/SystemUI/res/layout/status_bar_flip_button.xml b/packages/SystemUI/res/layout/status_bar_flip_button.xml
index db672ea..b7dff8c 100644
--- a/packages/SystemUI/res/layout/status_bar_flip_button.xml
+++ b/packages/SystemUI/res/layout/status_bar_flip_button.xml
@@ -16,7 +16,6 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/settings_button_holder"
android:layout_width="50dp"
android:layout_height="50dp">
<ImageView android:id="@+id/settings_button"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 2b01a06..61d43d7 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -23,6 +23,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
+ android:fitsSystemWindows="true"
android:descendantFocusability="afterDescendants">
<include layout="@layout/status_bar"
@@ -33,16 +34,11 @@
android:id="@+id/panel_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginTop="@dimen/panel_holder_padding_top"
- android:layout_marginBottom="@dimen/navigation_bar_height">
+ android:layout_marginTop="@dimen/panel_holder_padding_top">
<include layout="@layout/status_bar_expanded"
android:layout_width="@dimen/notification_panel_width"
android:layout_height="wrap_content"
android:layout_gravity="start|top" />
- <ViewStub android:id="@+id/quick_settings_stub"
- android:layout="@layout/quick_settings"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="match_parent" />
</com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index c6bc44d..fe2224e 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -20,9 +20,6 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
- <!-- Enable quick settings on tablets -->
- <bool name="config_hasSettingsPanel">true</bool>
-
<!-- The number of columns in the QuickSettings -->
<integer name="quick_settings_num_columns">3</integer>
@@ -31,7 +28,4 @@
<!-- The number of columns that the top level tiles span in the QuickSettings -->
<integer name="quick_settings_user_time_settings_tile_span">1</integer>
-
- <!-- Enable the "flip settings" panel -->
- <bool name="config_hasFlipSettingsPanel">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index b4fafec..5b5587d 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -23,10 +23,9 @@
<dimen name="notification_panel_margin_bottom">192dp</dimen>
<dimen name="notification_panel_margin_left">16dp</dimen>
- <!-- Gravity for the notification & quick settings panels -->
- <!-- 0x31 = top|center_horizontal ; 0x800035 = end|top -->
+ <!-- Gravity for the notification panel -->
+ <!-- 0x31 = top|center_horizontal -->
<integer name="notification_panel_layout_gravity">0x31</integer>
- <integer name="settings_panel_layout_gravity">0x800035</integer>
<!-- Diameter of outer shape drawable shown in navbar search-->
<dimen name="navbar_search_outerring_diameter">430dip</dimen>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f908a1e..722ca15 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -72,7 +72,7 @@
<!-- decay duration (from size_max -> size), in ms -->
<integer name="navigation_bar_deadzone_hold">333</integer>
<integer name="navigation_bar_deadzone_decay">333</integer>
-
+
<bool name="config_dead_zone_flash">false</bool>
<!-- Min alpha % that recent items will fade to while being dismissed -->
@@ -99,11 +99,8 @@
<integer name="blinds_pop_duration_ms">10</integer>
- <!-- Disable the separate quick settings panel -->
- <bool name="config_hasSettingsPanel">true</bool>
-
- <!-- Enable the "flip settings" panel -->
- <bool name="config_hasFlipSettingsPanel">true</bool>
+ <!-- The device supports quick settings. -->
+ <bool name="config_hasQuickSettings">true</bool>
<!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
<bool name="config_show4GForLTE">true</bool>
@@ -125,6 +122,9 @@
<!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
<integer name="recents_max_task_stack_view_dim">96</integer>
+ <!-- Whether to enable KeyguardService or not -->
+ <bool name="config_enableKeyguardService">true</bool>
+
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">4</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9aacf42..0604817 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -174,18 +174,9 @@
<dimen name="notification_panel_margin_bottom">0dp</dimen>
<dimen name="notification_panel_margin_left">0dp</dimen>
- <!-- Gravity for the notification & quick settings panels -->
+ <!-- Gravity for the notification panel -->
<!-- 0x37 = fill_horizontal|top -->
<integer name="notification_panel_layout_gravity">0x37</integer>
- <integer name="settings_panel_layout_gravity">0x37</integer>
-
- <!-- Fraction of the status bar that, when dragged, will produce the quick settings panel
- instead of the notification panel. See also @dimen/settings_panel_dragzone_min.
- If zero, the settings panel will not be directly draggable from the status bar. -->
- <item type="dimen" name="settings_panel_dragzone_fraction">0%</item>
-
- <!-- Quick settings dragzone, if used, should be at least this big (may be zero). -->
- <dimen name="settings_panel_dragzone_min">100dp</dimen>
<!-- Height of the carrier/wifi name label -->
<dimen name="carrier_label_height">24dp</dimen>
@@ -245,6 +236,12 @@
<!-- The amount of space a user has to scroll to dismiss any info panes. -->
<dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
+ <!-- The height of the search bar space. -->
+ <dimen name="recents_search_bar_space_height">40dp</dimen>
+
+ <!-- The search bar edge margins. -->
+ <dimen name="recents_search_bar_space_edge_margins">12dp</dimen>
+
<!-- Used to calculate the translation animation duration, the expected amount of movement
in dps over one second of time. -->
<dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
@@ -253,7 +250,7 @@
<dimen name="notification_stack_margin_bottom">0dp</dimen>
<!-- Space reserved for the cards behind the top card in the top stack -->
- <dimen name="top_stack_peek_amount">24dp</dimen>
+ <dimen name="top_stack_peek_amount">12dp</dimen>
<!-- Space reserved for the cards behind the top card in the bottom stack -->
<dimen name="bottom_stack_peek_amount">18dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 73e5e19..f3c956c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -511,6 +511,8 @@
<string name="recents_empty_message">RECENTS</string>
<!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
<string name="recents_app_info_button_label">Application Info</string>
+ <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] -->
+ <string name="recents_search_bar_label">search</string>
<!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
@@ -537,6 +539,9 @@
<!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
<string name="zen_mode_notification_text">Touch to show</string>
+ <!-- Zen mode: Short title. [CHAR LIMIT=40] -->
+ <string name="zen_mode_title">Do not disturb</string>
+
<!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
<plurals name="keyguard_more_overflow_text">
<item quantity="other">%d more</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 1832d37..8dd3f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -195,6 +195,12 @@
mGravity = Gravity.TOP;
mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
mScaleAnimation.setDuration(EXPAND_DURATION);
+ mScaleAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCallback.setUserLockedChild(mCurrView, false);
+ }
+ });
mPopLimit = mContext.getResources().getDimension(R.dimen.blinds_pop_threshold);
mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
@@ -549,8 +555,9 @@
mScaleAnimation.setFloatValues(targetHeight);
mScaleAnimation.setupStartValues();
mScaleAnimation.start();
+ } else {
+ mCallback.setUserLockedChild(mCurrView, false);
}
- mCallback.setUserLockedChild(mCurrView, false);
mExpanding = false;
mExpansionStyle = NONE;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index cb624ad..85befff 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -35,6 +35,9 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
}
+ protected void onBootCompleted() {
+ }
+
@SuppressWarnings("unchecked")
public <T> T getComponent(Class<T> interfaceType) {
return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 0f55683..103991a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -17,7 +17,12 @@
package com.android.systemui;
import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.os.SystemProperties;
import android.util.Log;
import java.util.HashMap;
@@ -49,6 +54,7 @@
*/
private final SystemUI[] mServices = new SystemUI[SERVICES.length];
private boolean mServicesStarted;
+ private boolean mBootCompleted;
private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
@Override
@@ -58,6 +64,23 @@
// application theme in the manifest does only work for activities. Keep this in sync with
// the theme set there.
setTheme(R.style.systemui_theme);
+
+ registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mBootCompleted) return;
+
+ if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
+ unregisterReceiver(this);
+ mBootCompleted = true;
+ if (mServicesStarted) {
+ final int N = mServices.length;
+ for (int i = 0; i < N; i++) {
+ mServices[i].onBootCompleted();
+ }
+ }
+ }
+ }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
}
/**
@@ -71,6 +94,17 @@
if (mServicesStarted) {
return;
}
+
+ if (!mBootCompleted) {
+ // check to see if maybe it was already completed long before we began
+ // see ActivityManagerService.finishBooting()
+ if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
+ mBootCompleted = true;
+ if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
+ }
+ }
+
+ Log.v(TAG, "Starting SystemUI services.");
final int N = SERVICES.length;
for (int i=0; i<N; i++) {
Class<?> cl = SERVICES[i];
@@ -86,6 +120,10 @@
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
+
+ if (mBootCompleted) {
+ mServices[i].onBootCompleted();
+ }
}
mServicesStarted = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index cbfc266..ffdb620 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -157,24 +157,6 @@
private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
/**
- * Allow the user to expand the status bar when the keyguard is engaged
- * (without a pattern or password).
- */
- private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
-
- /**
- * Allow the user to expand the status bar when a SECURE keyguard is engaged
- * and {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
- * (private notifications will be masked).
- */
- private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true;
-
- /**
- * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
- */
- private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
-
- /**
* Secure setting whether analytics are collected on the keyguard.
*/
private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
@@ -277,11 +259,6 @@
private int mLockSoundStreamId;
/**
- * Tracks value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
- */
- private boolean mAllowNotificationsWhenSecure;
-
- /**
* The volume applied to the lock/unlock sounds.
*/
private float mLockSoundVolume;
@@ -895,13 +872,6 @@
return;
}
- // note whether notification access should be allowed
- mAllowNotificationsWhenSecure = ENABLE_SECURE_STATUS_BAR_EXPAND
- && 0 != Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS,
- ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0);
-
// if the keyguard is already showing, don't bother
if (mStatusBarKeyguardViewManager.isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
@@ -1271,16 +1241,6 @@
// (like recents). Temporary enable/disable (e.g. the "back" button) are
// done in KeyguardHostView.
flags |= StatusBarManager.DISABLE_RECENT;
- if ((isSecure() && !mAllowNotificationsWhenSecure)
- || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
- // showing secure lockscreen; disable expanding.
- flags |= StatusBarManager.DISABLE_EXPAND;
- }
- if (isSecure()) {
- // showing secure lockscreen; disable ticker and switch private notifications
- // to show their public versions, if available.
- flags |= StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS;
- }
if (!isAssistantAvailable()) {
flags |= StatusBarManager.DISABLE_SEARCH;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index 10b6d49..21c2926 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -26,6 +26,7 @@
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.DisplayMetrics;
@@ -45,6 +46,7 @@
// Which recents to use
boolean mUseAlternateRecents;
AlternateRecentsComponent mAlternateRecents;
+ boolean mBootCompleted = false;
@Override
public void start() {
@@ -60,6 +62,11 @@
}
@Override
+ protected void onBootCompleted() {
+ mBootCompleted = true;
+ }
+
+ @Override
public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
if (mUseAlternateRecents) {
// Launch the alternate recents if required
@@ -197,13 +204,11 @@
Intent intent =
new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
intent.setPackage("com.android.systemui");
- mContext.sendBroadcastAsUser(intent,
- new UserHandle(UserHandle.USER_CURRENT));
+ sendBroadcastSafely(intent);
}
});
intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
+ startActivitySafely(intent, opts.toBundle());
}
} catch (ActivityNotFoundException e) {
Log.e(TAG, "Failed to launch RecentAppsIntent", e);
@@ -225,7 +230,7 @@
Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
"com.android.systemui.recent.RecentsPreloadReceiver");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ sendBroadcastSafely(intent);
RecentTasksLoader.getInstance(mContext).preloadFirstTask();
}
@@ -239,7 +244,7 @@
Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
"com.android.systemui.recent.RecentsPreloadReceiver");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ sendBroadcastSafely(intent);
RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
}
@@ -252,9 +257,25 @@
} else {
Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
intent.setPackage("com.android.systemui");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ sendBroadcastSafely(intent);
RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
}
}
+
+ /**
+ * Send broadcast only if BOOT_COMPLETED
+ */
+ private void sendBroadcastSafely(Intent intent) {
+ if (!mBootCompleted) return;
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+
+ /**
+ * Start activity only if BOOT_COMPLETED
+ */
+ private void startActivitySafely(Intent intent, Bundle opts) {
+ if (!mBootCompleted) return;
+ mContext.startActivityAsUser(intent, opts, new UserHandle(UserHandle.USER_CURRENT));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 4fb90cb..f2e322d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -44,6 +44,7 @@
import android.view.WindowManager;
import com.android.systemui.R;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -240,12 +241,10 @@
}
/** Returns whether there is are multiple recents tasks */
- boolean hasMultipleRecentsTask() {
+ boolean hasMultipleRecentsTask(List<ActivityManager.RecentTaskInfo> tasks) {
// NOTE: Currently there's no method to get the number of non-home tasks, so we have to
// compute this ourselves
SystemServicesProxy ssp = mSystemServicesProxy;
- List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(4,
- UserHandle.CURRENT.getIdentifier());
Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
while (iter.hasNext()) {
ActivityManager.RecentTaskInfo t = iter.next();
@@ -259,6 +258,17 @@
return (tasks.size() > 1);
}
+ /** Returns whether the base intent of the top task stack was launched with the flag
+ * Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. */
+ boolean isTopTaskExcludeFromRecents(List<ActivityManager.RecentTaskInfo> tasks) {
+ if (tasks.size() > 0) {
+ ActivityManager.RecentTaskInfo t = tasks.get(0);
+ Console.log(t.baseIntent.toString());
+ return (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
+ }
+ return false;
+ }
+
/** Converts from the device rotation to the degree */
float getDegreesForRotation(int value) {
switch (value) {
@@ -334,10 +344,18 @@
isTopTaskHome = ssp.isInHomeStack(topTask.id);
}
- // Otherwise, Recents is not the front-most activity and we should animate into it
- boolean hasMultipleTasks = hasMultipleRecentsTask();
+ // Otherwise, Recents is not the front-most activity and we should animate into it. If
+ // the activity at the root of the top task stack is excluded from recents, or if that
+ // task stack is in the home stack, then we just do a simple transition. Otherwise, we
+ // animate to the rects defined by the Recents service, which can differ depending on the
+ // number of items in the list.
+ List<ActivityManager.RecentTaskInfo> recentTasks =
+ ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier());
+ boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks);
+ boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks);
Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect;
- if (!isTopTaskHome && taskRect != null && taskRect.width() > 0 && taskRect.height() > 0) {
+ if (!isTopTaskHome && !isTaskExcludedFromRecents &&
+ (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) {
// Loading from thumbnail
Bitmap thumbnail;
Bitmap firstThumbnail = loadFirstTaskThumbnail();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 64770a4..72d9a52 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -29,6 +29,7 @@
public static final boolean EnableTaskFiltering = true;
public static final boolean EnableTaskStackClipping = false;
public static final boolean EnableInfoPane = true;
+ public static final boolean EnableSearchButton = false;
// This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
@@ -84,6 +85,9 @@
public static final int TaskStackOverscrollRange = 150;
public static final int FilterStartDelay = 25;
+ // The amount to inverse scale the movement if we are overscrolling
+ public static final float TouchOverscrollScaleFactor = 3f;
+
// The padding will be applied to the smallest dimension, and then applied to all sides
public static final float StackPaddingPct = 0.15f;
// The overlap height relative to the task height
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 5e5b841..d54df13 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -44,6 +44,8 @@
public int taskStackMaxDim;
public int taskViewInfoPaneAnimDuration;
public int taskViewRoundedCornerRadiusPx;
+ public int searchBarSpaceHeightPx;
+ public int searchBarSpaceEdgeMarginsPx;
public boolean launchedWithThumbnailAnimation;
@@ -92,6 +94,9 @@
res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
taskViewRoundedCornerRadiusPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+ searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
+ searchBarSpaceEdgeMarginsPx =
+ res.getDimensionPixelSize(R.dimen.recents_search_bar_space_edge_margins);
}
/** Updates the system insets */
@@ -99,6 +104,26 @@
systemInsets.set(insets);
}
+ /** Returns the search bar bounds in the specified orientation */
+ public void getSearchBarBounds(int width, int height,
+ Rect searchBarSpaceBounds, Rect searchBarBounds) {
+ // Return empty rects if search is not enabled
+ if (!Constants.DebugFlags.App.EnableSearchButton) {
+ searchBarSpaceBounds.set(0, 0, 0, 0);
+ searchBarBounds.set(0, 0, 0, 0);
+ return;
+ }
+
+ // Calculate the search bar bounds, and account for the system insets
+ int edgeMarginPx = searchBarSpaceEdgeMarginsPx;
+ int availableWidth = width - systemInsets.left - systemInsets.right;
+ searchBarSpaceBounds.set(0, 0, availableWidth, 2 * edgeMarginPx + searchBarSpaceHeightPx);
+
+ // Inset from the search bar space to get the search bar bounds
+ searchBarBounds.set(searchBarSpaceBounds);
+ searchBarBounds.inset(edgeMarginPx, edgeMarginPx);
+ }
+
/** Converts from DPs to PXs */
public int pxFromDp(float size) {
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 06ca9e2..36b761e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -66,22 +66,33 @@
Bundle replyData = new Bundle();
TaskViewTransform transform;
+ // Get the search bar bounds so that we can account for its height in the children
+ Rect searchBarSpaceBounds = new Rect();
+ Rect searchBarBounds = new Rect();
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ config.getSearchBarBounds(windowRect.width(), windowRect.height(),
+ searchBarSpaceBounds, searchBarBounds);
+
// Calculate the target task rect for when there is one task
// NOTE: Since the nav bar height is already accounted for in the windowRect, don't
// pass in a bottom inset
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
+ tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
+ systemInsets.bottom - searchBarSpaceBounds.height(), 0);
tsv.boundScroll();
transform = tsv.getStackTransform(0, tsv.getStackScroll());
+ transform.rect.offset(0, searchBarSpaceBounds.height());
replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT,
new Rect(transform.rect));
// Also calculate the target task rect when there are multiple tasks
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
+ tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
+ systemInsets.bottom - searchBarSpaceBounds.height(), 0);
tsv.setStackScrollRaw(Integer.MAX_VALUE);
tsv.boundScroll();
transform = tsv.getStackTransform(1, tsv.getStackScroll());
+ transform.rect.offset(0, searchBarSpaceBounds.height());
replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT,
new Rect(transform.rect));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index fd0f6d1..da265e1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -415,7 +415,10 @@
ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
t.activityLabel.toString());
- Bitmap activityIcon = t.activityIcon;
+ BitmapDrawable activityIcon = null;
+ if (t.activityIcon != null) {
+ activityIcon = new BitmapDrawable(res, t.activityIcon);
+ }
boolean isForemostTask = (i == (taskCount - 1));
// Create a new task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 7f0d9ee..33ac0a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -19,6 +19,8 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AppGlobals;
+import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,11 +28,15 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.Log;
import java.util.ArrayList;
import java.util.List;
@@ -45,6 +51,7 @@
PackageManager mPm;
IPackageManager mIpm;
UserManager mUm;
+ SearchManager mSm;
String mPackage;
Bitmap mDummyIcon;
@@ -55,6 +62,7 @@
mPm = context.getPackageManager();
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
+ mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
mPackage = context.getPackageName();
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
@@ -199,4 +207,28 @@
}
return icon;
}
+
+
+ /**
+ * Composes an intent to launch the global search activity.
+ */
+ public Intent getGlobalSearchIntent(Rect sourceBounds) {
+ if (mSm == null) return null;
+
+ // Try and get the global search activity
+ ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
+ if (globalSearchActivity == null) return null;
+
+ // Bundle the source of the search
+ Bundle appSearchData = new Bundle();
+ appSearchData.putString("source", mPackage);
+
+ // Compose the intent and Start the search activity
+ Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.setComponent(globalSearchActivity);
+ intent.putExtra(SearchManager.APP_DATA, appSearchData);
+ intent.setSourceBounds(sourceBounds);
+ return intent;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index ff062f6c..1566a49 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -69,8 +70,8 @@
public TaskKey key;
public Drawable applicationIcon;
+ public Drawable activityIcon;
public String activityLabel;
- public Bitmap activityIcon;
public Bitmap thumbnail;
public boolean isActive;
public int userId;
@@ -82,7 +83,7 @@
}
public Task(int id, boolean isActive, Intent intent, String activityTitle,
- Bitmap activityIcon, int userId) {
+ BitmapDrawable activityIcon, int userId) {
this.key = new TaskKey(id, intent, userId);
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index b054a22..a04cd3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -27,8 +27,11 @@
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
+import android.view.Gravity;
+import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
+import android.widget.TextView;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -36,6 +39,7 @@
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.R;
import java.util.ArrayList;
@@ -53,11 +57,16 @@
// The space partitioning root of this container
SpaceNode mBSP;
+ // Search bar view
+ View mSearchBar;
// Recents view callbacks
RecentsViewCallbacks mCb;
+ LayoutInflater mInflater;
+
public RecentsView(Context context) {
super(context);
+ mInflater = LayoutInflater.from(context);
setWillNotDraw(false);
}
@@ -71,12 +80,22 @@
mBSP = n;
// Create and add all the stacks for this partition of space.
+ boolean hasTasks = false;
removeAllViews();
ArrayList<TaskStack> stacks = mBSP.getStacks();
for (TaskStack stack : stacks) {
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
addView(stackView);
+ hasTasks |= (stack.getTaskCount() > 0);
+ }
+
+ // Create the search bar (and hide it if we have no recent tasks)
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ createSearchBar();
+ if (!hasTasks) {
+ mSearchBar.setVisibility(View.GONE);
+ }
}
}
@@ -85,29 +104,45 @@
// Get the first stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- TaskStackView stackView = (TaskStackView) getChildAt(i);
- TaskStack stack = stackView.mStack;
- ArrayList<Task> tasks = stack.getTasks();
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ TaskStackView stackView = (TaskStackView) child;
+ TaskStack stack = stackView.mStack;
+ ArrayList<Task> tasks = stack.getTasks();
- // Get the first task in the stack
- if (!tasks.isEmpty()) {
- Task task = tasks.get(tasks.size() - 1);
- TaskView tv = null;
+ // Get the first task in the stack
+ if (!tasks.isEmpty()) {
+ Task task = tasks.get(tasks.size() - 1);
+ TaskView tv = null;
- // Try and use the first child task view as the source of the launch animation
- if (stackView.getChildCount() > 0) {
- TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
- if (stv.getTask() == task) {
- tv = stv;
+ // Try and use the first child task view as the source of the launch animation
+ if (stackView.getChildCount() > 0) {
+ TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
+ if (stv.getTask() == task) {
+ tv = stv;
+ }
}
+ onTaskLaunched(stackView, tv, stack, task);
+ return true;
}
- onTaskLaunched(stackView, tv, stack, task);
- return true;
}
}
return false;
}
+ /** Creates and adds the search bar */
+ void createSearchBar() {
+ // Create a temporary search bar
+ mSearchBar = mInflater.inflate(R.layout.recents_search_bar, this, false);
+ mSearchBar.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onSearchTriggered();
+ }
+ });
+ addView(mSearchBar);
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -120,16 +155,26 @@
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
- // We measure our stack views sans the status bar. It will handle the nav bar itself.
+ // Get the search bar bounds so that we can account for its height in the children
+ Rect searchBarSpaceBounds = new Rect();
+ Rect searchBarBounds = new Rect();
RecentsConfiguration config = RecentsConfiguration.getInstance();
+ config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+ searchBarSpaceBounds, searchBarBounds);
+ if (mSearchBar != null) {
+ mSearchBar.measure(MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), widthMode),
+ MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), heightMode));
+ }
+
+ // We measure our stack views sans the status bar. It will handle the nav bar itself.
int childWidth = width - config.systemInsets.right;
- int childHeight = height - config.systemInsets.top;
+ int childHeight = height - config.systemInsets.top - searchBarSpaceBounds.height();
// Measure each child
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView && child.getVisibility() != GONE) {
child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
MeasureSpec.makeMeasureSpec(childHeight, heightMode));
}
@@ -145,18 +190,30 @@
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onLayout");
- // We offset our stack views by the status bar height. It will handle the nav bar itself.
+ // Get the search bar bounds so that we can account for its height in the children
+ Rect searchBarSpaceBounds = new Rect();
+ Rect searchBarBounds = new Rect();
RecentsConfiguration config = RecentsConfiguration.getInstance();
- top += config.systemInsets.top;
+ config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+ searchBarSpaceBounds, searchBarBounds);
+ if (mSearchBar != null) {
+ mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
+ config.systemInsets.top + searchBarSpaceBounds.top,
+ config.systemInsets.left + mSearchBar.getMeasuredWidth(),
+ config.systemInsets.top + mSearchBar.getMeasuredHeight());
+ }
+
+ // We offset our stack views by the status bar height. It will handle the nav bar itself.
+ top += config.systemInsets.top + searchBarSpaceBounds.height();
// Layout each child
// XXX: Based on the space node for that task view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- final int width = child.getMeasuredWidth();
- final int height = child.getMeasuredHeight();
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView && child.getVisibility() != GONE) {
+ int width = child.getMeasuredWidth();
+ int height = child.getMeasuredHeight();
child.layout(left, top, left + width, top + height);
}
}
@@ -188,9 +245,12 @@
// Get the first stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- TaskStackView stackView = (TaskStackView) getChildAt(i);
- if (stackView.closeOpenInfoPanes()) {
- return true;
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ TaskStackView stackView = (TaskStackView) child;
+ if (stackView.closeOpenInfoPanes()) {
+ return true;
+ }
}
}
}
@@ -266,7 +326,6 @@
b, offsetX, offsetY);
}
-
if (task.isActive) {
// Bring an active task to the foreground
RecentsTaskLoader.getInstance().getSystemServicesProxy()
@@ -315,4 +374,24 @@
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities();
}
+
+ public void onSearchTriggered() {
+ // Get the search bar source bounds
+ Rect searchBarSpaceBounds = new Rect();
+ Rect searchBarBounds = new Rect();
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+ searchBarSpaceBounds, searchBarBounds);
+
+ // Get the search intent and start it
+ Intent searchIntent = RecentsTaskLoader.getInstance().getSystemServicesProxy()
+ .getGlobalSearchIntent(searchBarBounds);
+ if (searchIntent != null) {
+ try {
+ getContext().startActivity(searchIntent);
+ } catch (ActivityNotFoundException anfe) {
+ Console.logError(getContext(), "Could not start Search activity");
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index c9a6d67..124f11e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -31,7 +31,6 @@
Task mTask;
ImageView mApplicationIcon;
- ImageView mActivityIcon;
TextView mActivityDescription;
public TaskBarView(Context context) {
@@ -54,23 +53,22 @@
protected void onFinishInflate() {
// Initialize the icon and description views
mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
- mActivityIcon = (ImageView) findViewById(R.id.activity_icon);
mActivityDescription = (TextView) findViewById(R.id.activity_description);
}
/** Binds the bar view to the task */
void rebindToTask(Task t, boolean animate) {
mTask = t;
- if (t.applicationIcon != null) {
+ // If an activity icon is defined, then we use that as the primary icon to show in the bar,
+ // otherwise, we fall back to the application icon
+ if (t.activityIcon != null) {
+ mApplicationIcon.setImageDrawable(t.activityIcon);
+ } else if (t.applicationIcon != null) {
mApplicationIcon.setImageDrawable(t.applicationIcon);
- mActivityDescription.setText(t.activityLabel);
- if (t.activityIcon != null) {
- mActivityIcon.setImageBitmap(t.activityIcon);
- mActivityIcon.setVisibility(View.VISIBLE);
- }
- if (animate) {
- // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
- }
+ }
+ mActivityDescription.setText(t.activityLabel);
+ if (animate) {
+ // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
}
}
@@ -78,8 +76,6 @@
void unbindFromTask() {
mTask = null;
mApplicationIcon.setImageDrawable(null);
- mActivityIcon.setImageBitmap(null);
- mActivityIcon.setVisibility(View.INVISIBLE);
mActivityDescription.setText("");
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
index 233e38c..a81d01c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -70,10 +70,8 @@
/** Updates the positions of each of the items to fit in the rect specified */
void updateContents(Rect visibleRect) {
// Offset the app info button
- LayoutParams lp = (LayoutParams) mAppInfoButton.getLayoutParams();
- lp.topMargin = visibleRect.top +
- (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2;
- requestLayout();
+ mAppInfoButton.setTranslationY(visibleRect.top +
+ (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2);
}
/** Sets the circular clip radius on this panel */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index ee92b16..a77e61d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -395,9 +395,12 @@
return false;
}
- /** Returns whether the current scroll is out of bounds */
+ /** Returns whether the specified scroll is out of bounds */
+ boolean isScrollOutOfBounds(int scroll) {
+ return (scroll < mMinScroll) || (scroll > mMaxScroll);
+ }
boolean isScrollOutOfBounds() {
- return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
+ return isScrollOutOfBounds(getStackScroll());
}
/** Updates the min and max virtual scroll bounds */
@@ -556,7 +559,14 @@
int smallestDimension = Math.min(width, height);
int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f);
- mStackRect.inset(padding, padding);
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ // Don't need to pad the top since we have some padding on the search bar already
+ mStackRect.left += padding;
+ mStackRect.right -= padding;
+ mStackRect.bottom -= padding;
+ } else {
+ mStackRect.inset(padding, padding);
+ }
mStackRectSansPeek.set(mStackRect);
mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
@@ -1275,7 +1285,12 @@
}
}
if (mIsScrolling) {
- mSv.setStackScroll(mSv.getStackScroll() + deltaY);
+ int curStackScroll = mSv.getStackScroll();
+ if (mSv.isScrollOutOfBounds(curStackScroll + deltaY)) {
+ // Scale the touch if we are overscrolling
+ deltaY /= Constants.Values.TaskStackView.TouchOverscrollScaleFactor;
+ }
+ mSv.setStackScroll(curStackScroll + deltaY);
if (mSv.isScrollOutOfBounds()) {
mVelocityTracker.clear();
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
index 87ebcc1..d67e7cb 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
@@ -38,6 +38,7 @@
import android.widget.TextView;
import java.util.ArrayList;
+import java.util.List;
/**
* A quick and dirty view to show a user switcher.
@@ -118,7 +119,12 @@
public void refreshUsers() {
mUserInfo.clear();
- mUserInfo.addAll(mUserManager.getUsers(true));
+ List<UserInfo> users = mUserManager.getUsers(true);
+ for (UserInfo user : users) {
+ if (!user.isManagedProfile()) {
+ mUserInfo.add(user);
+ }
+ }
mAdapter.notifyDataSetChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index fdf4dbf..bb481ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -54,6 +54,7 @@
private boolean mMaxHeightNeedsUpdate;
private NotificationActivator mActivator;
private LatestItemView.OnActivatedListener mOnActivatedListener;
+ private boolean mSelfInitiatedLayout;
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -162,15 +163,28 @@
}
private void updateMaxExpandHeight() {
+
+ // We don't want this method to trigger a layout of the whole view hierarchy,
+ // as the layout parameters in the end are the same which they were in the beginning.
+ // Otherwise a loop may occur if this method is called on the layout of a parent.
+ mSelfInitiatedLayout = true;
ViewGroup.LayoutParams lp = getLayoutParams();
int oldHeight = lp.height;
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
setLayoutParams(lp);
- measure(View.MeasureSpec.makeMeasureSpec(getMeasuredWidth(), View.MeasureSpec.EXACTLY),
+ measure(View.MeasureSpec.makeMeasureSpec(getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(mRowMaxHeight, View.MeasureSpec.AT_MOST));
lp.height = oldHeight;
setLayoutParams(lp);
mMaxExpandHeight = getMeasuredHeight();
+ mSelfInitiatedLayout = false;
+ }
+
+ @Override
+ public void requestLayout() {
+ if (!mSelfInitiatedLayout) {
+ super.requestLayout();
+ }
}
/**
@@ -257,4 +271,11 @@
public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
mLatestItemView.setBackgroundResourceIds(bgResId, dimmedBgResId);
}
+
+ /**
+ * @return the potential height this view could expand in addition.
+ */
+ public int getExpandPotential() {
+ return getMaximumAllowedExpandHeight() - getHeight();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
new file mode 100644
index 0000000..3cc22ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 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.systemui.statusbar.phone;
+
+import android.app.ActivityManagerNative;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+/**
+ * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
+ * text.
+ */
+public class KeyguardBottomAreaView extends FrameLayout {
+
+ final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
+
+ private View mCameraButton;
+ private float mCameraDragDistance;
+ private PowerManager mPowerManager;
+ private int mScaledTouchSlop;
+
+ public KeyguardBottomAreaView(Context context) {
+ super(context);
+ }
+
+ public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mCameraButton = findViewById(R.id.camera_button);
+ watchForDevicePolicyChanges();
+ watchForAccessibilityChanges();
+ updateCameraVisibility();
+ mCameraDragDistance = getResources().getDimension(R.dimen.camera_drag_distance);
+ mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ }
+
+ private void updateCameraVisibility() {
+ boolean visible = !isCameraDisabledByDpm();
+ mCameraButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
+ private boolean isCameraDisabledByDpm() {
+ final DevicePolicyManager dpm =
+ (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm != null) {
+ try {
+ final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
+ final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
+ final boolean disabledBecauseKeyguardSecure =
+ (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
+ && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
+ return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't get userId", e);
+ }
+ }
+ return false;
+ }
+
+ private void watchForDevicePolicyChanges() {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ getContext().registerReceiver(new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ updateCameraVisibility();
+ }
+ });
+ }
+ }, filter);
+ }
+
+ private void watchForAccessibilityChanges() {
+ final AccessibilityManager am =
+ (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+ // Set the initial state
+ enableAccessibility(am.isTouchExplorationEnabled());
+
+ // Watch for changes
+ am.addTouchExplorationStateChangeListener(
+ new AccessibilityManager.TouchExplorationStateChangeListener() {
+ @Override
+ public void onTouchExplorationStateChanged(boolean enabled) {
+ enableAccessibility(enabled);
+ }
+ });
+ }
+
+ private void enableAccessibility(boolean touchExplorationEnabled) {
+
+ // Add a touch handler or accessibility click listener for camera button.
+ if (touchExplorationEnabled) {
+ mCameraButton.setOnTouchListener(null);
+ mCameraButton.setOnClickListener(mCameraClickListener);
+ } else {
+ mCameraButton.setOnTouchListener(mCameraTouchListener);
+ mCameraButton.setOnClickListener(null);
+ }
+ }
+
+ private void launchCamera() {
+ mContext.startActivityAsUser(
+ new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
+ UserHandle.CURRENT);
+ }
+
+ private final OnClickListener mCameraClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ launchCamera();
+ }
+ };
+
+ private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
+ private float mStartX;
+ private boolean mTouchSlopReached;
+ private boolean mSkipCancelAnimation;
+
+ @Override
+ public boolean onTouch(final View cameraButtonView, MotionEvent event) {
+ float realX = event.getRawX();
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mStartX = realX;
+ mTouchSlopReached = false;
+ mSkipCancelAnimation = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (realX > mStartX) {
+ realX = mStartX;
+ }
+ if (realX < mStartX - mCameraDragDistance) {
+ cameraButtonView.setPressed(true);
+ mPowerManager.userActivity(event.getEventTime(), false);
+ } else {
+ cameraButtonView.setPressed(false);
+ }
+ if (realX < mStartX - mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ cameraButtonView.setTranslationX(Math.max(realX - mStartX,
+ -mCameraDragDistance));
+ break;
+ case MotionEvent.ACTION_UP:
+ if (realX < mStartX - mCameraDragDistance) {
+ launchCamera();
+ cameraButtonView.animate().x(-cameraButtonView.getWidth())
+ .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ cameraButtonView.setTranslationX(0);
+ }
+ });
+ mSkipCancelAnimation = true;
+ }
+ if (realX < mStartX - mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ if (!mTouchSlopReached) {
+ mSkipCancelAnimation = true;
+ cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
+ setInterpolator(new DecelerateInterpolator()).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ cameraButtonView.animate().translationX(0).
+ setInterpolator(new AccelerateInterpolator());
+ }
+ });
+ }
+ case MotionEvent.ACTION_CANCEL:
+ cameraButtonView.setPressed(false);
+ if (!mSkipCancelAnimation) {
+ cameraButtonView.animate().translationX(0)
+ .setInterpolator(new AccelerateInterpolator(2f));
+ }
+ break;
+ }
+ return true;
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index f2054a2..1ffb4ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -83,7 +83,7 @@
}
public void onScreenTurnedOff() {
- if (mKeyguardView != null && mRoot.getVisibility() == View.VISIBLE) {
+ if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
mKeyguardView.onPause();
}
}
@@ -143,6 +143,10 @@
return false;
}
+ public boolean isSecure() {
+ return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
+ }
+
public boolean onMenuPressed() {
ensureView();
if (mKeyguardView.handleMenuKey()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index d26b32f..a0582ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -82,7 +82,6 @@
setKeyButtonViewQuiescentAlpha(mView.getMenuButton(), alpha, animate);
setKeyButtonViewQuiescentAlpha(mView.getSearchLight(), KEYGUARD_QUIESCENT_ALPHA, animate);
- setKeyButtonViewQuiescentAlpha(mView.getCameraButton(), KEYGUARD_QUIESCENT_ALPHA, animate);
applyBackButtonQuiescentAlpha(mode, animate);
@@ -98,7 +97,6 @@
public void applyBackButtonQuiescentAlpha(int mode, boolean animate) {
float backAlpha = 0;
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getSearchLight());
- backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getCameraButton());
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getHomeButton());
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getRecentsButton());
backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getMenuButton());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7ca672d..3fae3f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,36 +21,24 @@
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
-import android.app.ActivityManagerNative;
import android.app.StatusBarManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.MediaStore;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -63,8 +51,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import static com.android.systemui.statusbar.phone.KeyguardTouchDelegate.OnKeyguardConnectionListener;
-
public class NavigationBarView extends LinearLayout {
final static boolean DEBUG = false;
final static String TAG = "PhoneStatusBar/NavigationBarView";
@@ -98,16 +84,9 @@
final static boolean WORKAROUND_INVALID_LAYOUT = true;
final static int MSG_CHECK_INVALID_LAYOUT = 8686;
- private final float mCameraDragDistance;
-
- // used to disable the camera icon in navbar when disabled by DPM
- private boolean mCameraDisabledByDpm;
-
// performs manual animation in sync with layout transitions
private final NavTransitionListener mTransitionListener = new NavTransitionListener();
- private final PowerManager mPowerManager;
-
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -157,112 +136,12 @@
private final OnClickListener mAccessibilityClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (v.getId() == R.id.camera_button) {
- KeyguardTouchDelegate.getInstance(getContext()).launchCamera();
- } else if (v.getId() == R.id.search_light) {
+ if (v.getId() == R.id.search_light) {
KeyguardTouchDelegate.getInstance(getContext()).showAssistant();
}
}
};
- private final int mScaledTouchSlop;
-
- private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
- private float mStartX;
- private boolean mTouchSlopReached;
- private boolean mSkipCancelAnimation;
-
- @Override
- public boolean onTouch(final View cameraButtonView, MotionEvent event) {
- float realX = event.getRawX();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- // disable search gesture while interacting with camera
- mDelegateHelper.setDisabled(true);
- mBarTransitions.setContentVisible(false);
- mStartX = realX;
- mTouchSlopReached = false;
- mSkipCancelAnimation = false;
- break;
- case MotionEvent.ACTION_MOVE:
- if (realX > mStartX) {
- realX = mStartX;
- }
- if (realX < mStartX - mCameraDragDistance) {
- ((KeyButtonView) cameraButtonView).setPressed(true);
- mPowerManager.userActivity(event.getEventTime(), false);
- } else {
- ((KeyButtonView) cameraButtonView).setPressed(false);
- }
- if (realX < mStartX - mScaledTouchSlop) {
- mTouchSlopReached = true;
- }
- cameraButtonView.setTranslationX(Math.max(realX - mStartX,
- -mCameraDragDistance));
- break;
- case MotionEvent.ACTION_UP:
- if (realX < mStartX - mCameraDragDistance) {
- mContext.startActivityAsUser(
- new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
- UserHandle.CURRENT);
- cameraButtonView.animate().x(-cameraButtonView.getWidth())
- .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
- new Runnable() {
- @Override
- public void run() {
- cameraButtonView.setTranslationX(0);
- }
- });
- mSkipCancelAnimation = true;
- }
- if (realX < mStartX - mScaledTouchSlop) {
- mTouchSlopReached = true;
- }
- if (!mTouchSlopReached) {
- mSkipCancelAnimation = true;
- cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
- setInterpolator(new DecelerateInterpolator()).withEndAction(
- new Runnable() {
- @Override
- public void run() {
- cameraButtonView.animate().translationX(0).
- setInterpolator(new AccelerateInterpolator());
- }
- });
- }
- case MotionEvent.ACTION_CANCEL:
- ((KeyButtonView) cameraButtonView).setPressed(false);
- mDelegateHelper.setDisabled(false);
- mBarTransitions.setContentVisible(true);
- if (!mSkipCancelAnimation) {
- cameraButtonView.animate().translationX(0)
- .setInterpolator(new AccelerateInterpolator(2f));
- }
- break;
- }
- return true;
- }
- };
-
- private final OnKeyguardConnectionListener mKeyguardConnectionListener =
- new OnKeyguardConnectionListener() {
- @Override
- public void onKeyguardServiceConnected(
- KeyguardTouchDelegate keyguardTouchDelegate) {
- post(new Runnable() {
- @Override
- public void run() {
- mCameraDisabledByDpm = isCameraDisabledByDpm();
- }
- });
- }
-
- @Override
- public void onKeyguardServiceDisconnected(
- KeyguardTouchDelegate keyguardTouchDelegate) {
- }
- };
-
private class H extends Handler {
public void handleMessage(Message m) {
switch (m.what) {
@@ -301,28 +180,6 @@
getIcons(res);
mBarTransitions = new NavigationBarTransitions(this);
-
- KeyguardTouchDelegate.addListener(mKeyguardConnectionListener);
- mCameraDisabledByDpm = isCameraDisabledByDpm();
- watchForDevicePolicyChanges();
- mCameraDragDistance = res.getDimension(R.dimen.camera_drag_distance);
- mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- }
-
- private void watchForDevicePolicyChanges() {
- final IntentFilter filter = new IntentFilter();
- filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- getContext().registerReceiver(new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- post(new Runnable() {
- @Override
- public void run() {
- mCameraDisabledByDpm = isCameraDisabledByDpm();
- }
- });
- }
- }, filter);
}
public BarTransitions getBarTransitions() {
@@ -381,11 +238,6 @@
return mCurrentView.findViewById(R.id.search_light);
}
- // shown when keyguard is visible and camera is available
- public View getCameraButton() {
- return mCurrentView.findViewById(R.id.camera_button);
- }
-
private void getIcons(Resources res) {
mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land);
@@ -475,9 +327,7 @@
getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
final boolean showSearch = disableHome && !disableSearch;
- final boolean showCamera = showSearch && !mCameraDisabledByDpm;
setVisibleOrGone(getSearchLight(), showSearch);
- setVisibleOrGone(getCameraButton(), showCamera);
mBarTransitions.applyBackButtonQuiescentAlpha(mBarTransitions.getMode(), true /*animate*/);
}
@@ -488,24 +338,6 @@
}
}
- private boolean isCameraDisabledByDpm() {
- final DevicePolicyManager dpm =
- (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
- if (dpm != null) {
- try {
- final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
- final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
- final boolean disabledBecauseKeyguardSecure =
- (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
- && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
- return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
- } catch (RemoteException e) {
- Log.e(TAG, "Can't get userId", e);
- }
- }
- return false;
- }
-
public void setSlippery(boolean newSlippery) {
WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
if (lp != null) {
@@ -572,25 +404,12 @@
// Add a touch handler or accessibility click listener for camera and search buttons
// for all view orientations.
final OnClickListener onClickListener = touchEnabled ? mAccessibilityClickListener : null;
- final OnTouchListener onTouchListener = touchEnabled ? null : mCameraTouchListener;
- boolean hasCamera = false;
for (int i = 0; i < mRotatedViews.length; i++) {
- final View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button);
final View searchLight = mRotatedViews[i].findViewById(R.id.search_light);
- if (cameraButton != null) {
- hasCamera = true;
- cameraButton.setOnTouchListener(onTouchListener);
- cameraButton.setOnClickListener(onClickListener);
- }
if (searchLight != null) {
searchLight.setOnClickListener(onClickListener);
}
}
- if (hasCamera) {
- // Warm up KeyguardTouchDelegate so it's ready by the time the camera button is touched.
- // This will connect to KeyguardService so that touch events are processed.
- KeyguardTouchDelegate.getInstance(getContext());
- }
}
public boolean isVertical() {
@@ -727,7 +546,6 @@
dumpButton(pw, "rcnt", getRecentsButton());
dumpButton(pw, "menu", getMenuButton());
dumpButton(pw, "srch", getSearchLight());
- dumpButton(pw, "cmra", getCameraButton());
pw.println(" }");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 45ac50b..5d75801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -38,6 +38,7 @@
private int[] mTempChildLocation = new int[2];
private View mNotificationParent;
private boolean mTrackingSettings;
+ private float mExpandedHeight = -1;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -173,6 +174,8 @@
* @param expandedHeight the new expanded height
*/
private void updateNotificationStackHeight(float expandedHeight) {
+ if (mExpandedHeight == expandedHeight) return;
+ mExpandedHeight = expandedHeight;
mNotificationStackScroller.setIsExpanded(expandedHeight > 0.0f);
float childOffset = getRelativeTop(mNotificationStackScroller)
- mNotificationParent.getTranslationY();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 0266144c..328a1728 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -46,7 +46,6 @@
}
public static final boolean BRAKES = false;
- private boolean mRubberbandingEnabled = true;
private float mSelfExpandVelocityPx; // classic value: 2000px/s
private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -68,14 +67,12 @@
private float mExpandBrakingDistancePx = 150; // XXX Resource
private float mBrakingSpeedPx = 150; // XXX Resource
- private View mHandleView;
private float mPeekHeight;
private float mInitialOffsetOnTouch;
private float mExpandedFraction = 0;
private float mExpandedHeight = 0;
private boolean mJustPeeked;
private boolean mClosing;
- private boolean mRubberbanding;
private boolean mTracking;
private int mTrackingPointer;
private int mTouchSlop;
@@ -214,7 +211,6 @@
public void run() {
if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
mTimeAnimator.end();
- mRubberbanding = false;
mClosing = false;
onExpandingFinished();
}
@@ -225,12 +221,9 @@
protected int mMaxPanelHeight = 0;
private String mViewName;
protected float mInitialTouchY;
+ protected float mInitialTouchX;
protected float mFinalTouchY;
- public void setRubberbandingEnabled(boolean enable) {
- mRubberbandingEnabled = enable;
- }
-
protected void onExpandingFinished() {
}
@@ -260,12 +253,7 @@
mTimeAnimator.start();
- mRubberbanding = mRubberbandingEnabled // is it enabled at all?
- && mExpandedHeight > getMaxPanelHeight() // are we past the end?
- && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
- if (mRubberbanding) {
- mClosing = true;
- } else if (mVel == 0) {
+ if (mVel == 0) {
// if the panel is less than halfway open, close it
mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f;
} else {
@@ -308,10 +296,6 @@
float h = mExpandedHeight + mVel * dt;
- if (mRubberbanding && h < fh) {
- h = fh;
- }
-
if (DEBUG) logf("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
setExpandedHeightInternal(h);
@@ -320,7 +304,7 @@
if (mVel == 0
|| (mClosing && mExpandedHeight == 0)
- || ((mRubberbanding || !mClosing) && mExpandedHeight == fh)) {
+ || (!mClosing && mExpandedHeight == fh)) {
post(mStopAnimator);
}
} else {
@@ -358,8 +342,7 @@
mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
mPeekHeight = res.getDimension(R.dimen.peek_height)
- + getPaddingBottom() // our window might have a dropshadow
- - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
+ + getPaddingBottom(); // our window might have a dropshadow
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
@@ -393,16 +376,14 @@
mTrackingPointer = event.getPointerId(pointerIndex);
}
final float y = event.getY(pointerIndex);
+ final float x = event.getX(pointerIndex);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mTracking = true;
- if (mHandleView != null) {
- mHandleView.setPressed(true);
- postInvalidate(); // catch the press state change
- }
mInitialTouchY = y;
+ mInitialTouchX = x;
initVelocityTracker();
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
@@ -420,9 +401,11 @@
// gesture is ongoing, find a new pointer to track
final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
final float newY = event.getY(newIndex);
+ final float newX = event.getX(newIndex);
mTrackingPointer = event.getPointerId(newIndex);
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = newY;
+ mInitialTouchX = newX;
}
break;
@@ -447,10 +430,6 @@
mFinalTouchY = y;
mTracking = false;
mTrackingPointer = -1;
- if (mHandleView != null) {
- mHandleView.setPressed(false);
- postInvalidate(); // catch the press state change
- }
onTrackingStopped();
trackMovement(event);
@@ -541,23 +520,17 @@
pointerIndex = 0;
mTrackingPointer = event.getPointerId(pointerIndex);
}
+ final float x = event.getX(pointerIndex);
final float y = event.getY(pointerIndex);
boolean scrolledToBottom = isScrolledToBottom();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- if (mHandleView != null) {
- mHandleView.setPressed(true);
- // catch the press state change
- postInvalidate();
- }
mInitialTouchY = y;
+ mInitialTouchX = x;
initVelocityTracker();
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
- if (mExpandedHeight == 0 || y > getContentHeight()) {
- return true;
- }
break;
case MotionEvent.ACTION_POINTER_UP:
final int upPointer = event.getPointerId(event.getActionIndex());
@@ -565,8 +538,8 @@
// gesture is ongoing, find a new pointer to track
final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
mTrackingPointer = event.getPointerId(newIndex);
- final float newY = event.getY(newIndex);
- mInitialTouchY = newY;
+ mInitialTouchX = event.getX(newIndex);
+ mInitialTouchY = event.getY(newIndex);
}
break;
@@ -574,9 +547,10 @@
final float h = y - mInitialTouchY;
trackMovement(event);
if (scrolledToBottom) {
- if (h < -mTouchSlop) {
+ if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = y;
+ mInitialTouchX = x;
mTracking = true;
onTrackingStarted();
return true;
@@ -605,7 +579,6 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mHandleView = findViewById(R.id.handle);
loadDimens();
}
@@ -631,10 +604,6 @@
return mViewName;
}
- public View getHandle() {
- return mHandleView;
- }
-
// Rubberbands the panel to hold its contents.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@@ -648,14 +617,14 @@
if (newHeight != mMaxPanelHeight) {
mMaxPanelHeight = newHeight;
// If the user isn't actively poking us, let's rubberband to the content
- if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+ if (!mTracking && !mTimeAnimator.isStarted()
&& mExpandedHeight > 0 && mExpandedHeight != mMaxPanelHeight
&& mMaxPanelHeight > 0) {
mExpandedHeight = mMaxPanelHeight;
}
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
+ getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
@@ -666,7 +635,6 @@
public void setExpandedHeight(float height) {
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
- mRubberbanding = false;
if (mTimeAnimator.isStarted()) {
post(mStopAnimator);
}
@@ -686,7 +654,7 @@
float currentMaxPanelHeight = getMaxPanelHeight();
// If the user isn't actively poking us, let's update the height
- if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+ if (!mTracking && !mTimeAnimator.isStarted()
&& mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) {
setExpandedHeightInternal(currentMaxPanelHeight);
}
@@ -708,13 +676,13 @@
}
if (h < 0) h = 0;
- if (!(mRubberbandingEnabled && (mTracking || mRubberbanding)) && h > fh) h = fh;
+ if (h > fh) h = fh;
mExpandedHeight = h;
if (DEBUG) {
- logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh,
- mTracking ? "T" : "f", mRubberbanding ? "T" : "f");
+ logf("setExpansion: height=%.1f fh=%.1f tracking=%s", h, fh,
+ mTracking ? "T" : "f");
}
onHeightUpdated(mExpandedHeight);
@@ -793,7 +761,6 @@
mClosing = true;
onExpandingStarted();
// collapse() should never be a rubberband, even if an animation is already running
- mRubberbanding = false;
fling(-mSelfCollapseVelocityPx, /*always=*/ true);
}
}
@@ -817,14 +784,13 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
- + " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+ + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+ "]",
this.getClass().getSimpleName(),
getExpandedHeight(),
getMaxPanelHeight(),
mClosing?"T":"f",
mTracking?"T":"f",
- mRubberbanding?"T":"f",
mJustPeeked?"T":"f",
mPeekAnimator, ((mPeekAnimator!=null && mPeekAnimator.isStarted())?" (started)":""),
mTimeAnimator, ((mTimeAnimator!=null && mTimeAnimator.isStarted())?" (started)":"")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d577070..7f1ddaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -25,7 +25,6 @@
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
-import static com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -77,7 +76,7 @@
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
+import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
@@ -147,6 +146,11 @@
private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
+ /**
+ * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+ */
+ private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
+
private static final int STATUS_OR_NAV_TRANSIENT =
View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
private static final long AUTOHIDE_TIMEOUT_MS = 3000;
@@ -220,15 +224,14 @@
// settings
QuickSettings mQS;
- boolean mHasSettingsPanel, mHasFlipSettings;
- SettingsPanelView mSettingsPanel;
+ boolean mHasQuickSettings;
View mFlipSettingsView;
QuickSettingsContainerView mSettingsContainer;
- int mSettingsPanelGravity;
// top bar
View mNotificationPanelHeader;
View mKeyguardStatusView;
+ View mKeyguardBottomArea;
int mKeyguardMaxNotificationCount;
View mDateTimeView;
View mClearButton;
@@ -315,9 +318,6 @@
mHeaderFlipper.userSetup(userSetup);
mKeyguardFlipper.userSetup(userSetup);
- if (mSettingsPanel != null) {
- mSettingsPanel.setEnabled(userSetup);
- }
if (userSetup != mUserSetup) {
mUserSetup = userSetup;
if (!mUserSetup && mStatusBarView != null)
@@ -617,6 +617,7 @@
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+ mKeyguardBottomArea = mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
mClearButton.setOnClickListener(mClearButtonListener);
@@ -625,8 +626,7 @@
mClearButton.setEnabled(false);
mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
- mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel);
- mHasFlipSettings = res.getBoolean(R.bool.config_hasFlipSettingsPanel);
+ mHasQuickSettings = res.getBoolean(R.bool.config_hasQuickSettings);
mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
if (mDateTimeView != null) {
@@ -634,10 +634,8 @@
mDateTimeView.setEnabled(true);
}
- mHeaderFlipper = new FlipperButton(mNotificationPanelHeader
- .findViewById(R.id.settings_button_holder));
- ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
- mKeyguardFlipper = new FlipperButton(flipStub.inflate());
+ mHeaderFlipper = new FlipperButton(mStatusBarWindow.findViewById(R.id.header_flipper));
+ mKeyguardFlipper =new FlipperButton(mStatusBarWindow.findViewById(R.id.keyguard_flipper));
if (!mNotificationPanelIsFullScreenWidth) {
mNotificationPanel.setSystemUiVisibility(
@@ -715,37 +713,11 @@
// Quick Settings (where available, some restrictions apply)
mNotificationPadding = mContext.getResources()
.getDimensionPixelSize(R.dimen.notification_side_padding);
- if (mHasSettingsPanel) {
- // first, figure out where quick settings should be inflated
- final View settings_stub;
- if (mHasFlipSettings) {
- // a version of quick settings that flips around behind the notifications
- settings_stub = mStatusBarWindow.findViewById(R.id.flip_settings_stub);
- if (settings_stub != null) {
- mFlipSettingsView = ((ViewStub)settings_stub).inflate();
- mFlipSettingsView.setVisibility(View.GONE);
- mFlipSettingsView.setVerticalScrollBarEnabled(false);
- }
- } else {
- // full quick settings panel
- settings_stub = mStatusBarWindow.findViewById(R.id.quick_settings_stub);
- if (settings_stub != null) {
- mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate();
- } else {
- mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
- }
-
- if (mSettingsPanel != null) {
- if (!ActivityManager.isHighEndGfx()) {
- mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
- R.color.notification_panel_solid_background)));
- }
- }
- }
-
- // wherever you find it, Quick Settings needs a container to survive
+ if (mHasQuickSettings) {
+ // Quick Settings needs a container to survive
mSettingsContainer = (QuickSettingsContainerView)
mStatusBarWindow.findViewById(R.id.quick_settings_container);
+ mFlipSettingsView = mSettingsContainer;
if (mSettingsContainer != null) {
mQS = new QuickSettings(mContext, mSettingsContainer);
if (!mNotificationPanelIsFullScreenWidth) {
@@ -753,9 +725,6 @@
View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS
| View.STATUS_BAR_DISABLE_SYSTEM_INFO);
}
- if (mSettingsPanel != null) {
- mSettingsPanel.setQuickSettings(mQS);
- }
mQS.setService(this);
mQS.setBar(mStatusBarView);
mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
@@ -784,6 +753,11 @@
}
public boolean onSettingsEvent(MotionEvent event) {
+ userActivity();
+ if (mSettingsClosing
+ && mFlipSettingsViewAnim != null && mFlipSettingsViewAnim.isRunning()) {
+ return true;
+ }
if (mSettingsTracker != null) {
mSettingsTracker.addMovement(event);
}
@@ -810,10 +784,11 @@
if (!qsTap && !inButton) {
mSettingsTracker.computeCurrentVelocity(1000);
final float vy = mSettingsTracker.getYVelocity();
+ final boolean animate = true;
if (dy <= slop || vy <= 0) {
- flipToNotifications();
+ flipToNotifications(animate);
} else {
- flipToSettings();
+ flipToSettings(animate);
}
}
mSettingsTracker.recycle();
@@ -851,15 +826,15 @@
}
private void positionSettings(float dy) {
- final int h = mFlipSettingsView.getMeasuredHeight();
- final int ph = mNotificationPanel.getMeasuredHeight();
if (mSettingsClosing) {
+ final int ph = mNotificationPanel.getMeasuredHeight();
dy = Math.min(Math.max(-ph, dy), 0);
mFlipSettingsView.setTranslationY(dy);
mStackScroller.setTranslationY(ph + dy);
} else {
- dy = Math.min(Math.max(0, dy), ph);
- mFlipSettingsView.setTranslationY(-h + dy - mNotificationPadding * 2);
+ final int h = mFlipSettingsView.getBottom();
+ dy = Math.min(Math.max(0, dy), h);
+ mFlipSettingsView.setTranslationY(-h + dy);
mStackScroller.setTranslationY(dy);
}
}
@@ -1397,8 +1372,7 @@
+ " any=" + any + " clearable=" + clearable);
}
- if (mHasFlipSettings
- && mFlipSettingsView != null
+ if (mFlipSettingsView != null
&& mFlipSettingsView.getVisibility() == View.VISIBLE
&& mStackScroller.getVisibility() != View.VISIBLE) {
// the flip settings panel is unequivocally showing; we should not be shown
@@ -1482,8 +1456,6 @@
flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " ");
flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts");
flagdbg.append(((diff & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " ");
- flagdbg.append(((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "PRIVATE" : "private");
- flagdbg.append(((diff & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "* " : " ");
flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info");
flagdbg.append(((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " ");
flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back");
@@ -1568,15 +1540,6 @@
.setDuration(175)
.start();
}
- } else if ((diff & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) {
- if ((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) {
- // we are outside a secure keyguard, so we need to switch to "public" mode
- setLockscreenPublicMode(true);
- } else {
- // user has authenticated the device; full notifications may be shown
- setLockscreenPublicMode(false);
- }
- updateNotificationIcons();
}
}
@@ -1699,7 +1662,7 @@
mStatusBarWindow.cancelExpandHelper();
mStatusBarView.collapseAllPanels(true);
if (isFlippedToSettings()) {
- flipToNotifications();
+ flipToNotifications(true /*animate*/);
}
}
}
@@ -1758,39 +1721,50 @@
}
mNotificationPanel.expand();
- if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) {
- flipToNotifications();
+ if (mStackScroller.getVisibility() != View.VISIBLE) {
+ flipToNotifications(true /*animate*/);
}
if (false) postStartTracing();
}
- public void flipToNotifications() {
- if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
- if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ private static void cancelAnim(Animator anim) {
+ if (anim != null) {
+ anim.cancel();
+ }
+ }
+
+ public void flipToNotifications(boolean animate) {
+ cancelAnim(mFlipSettingsViewAnim);
+ cancelAnim(mScrollViewAnim);
+ cancelAnim(mClearButtonAnim);
mHeaderFlipper.cancel();
mKeyguardFlipper.cancel();
- if (mClearButtonAnim != null) mClearButtonAnim.cancel();
-
mStackScroller.setVisibility(View.VISIBLE);
final int h = mNotificationPanel.getMeasuredHeight();
- final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0;
- final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h;
- mScrollViewAnim = start(
- startDelay(0,
- interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0)
- .setDuration(FLIP_DURATION)
- )));
- mFlipSettingsViewAnim = start(
- setVisibilityWhenDone(
- interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h)
- )
- .setDuration(FLIP_DURATION),
- mFlipSettingsView, View.INVISIBLE));
- mHeaderFlipper.flipToNotifications();
- mKeyguardFlipper.flipToNotifications();
+ if (animate) {
+ final float settingsY =
+ mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0;
+ final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h;
+ mScrollViewAnim = start(
+ interpolator(mDecelerateInterpolator,
+ ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0)
+ .setDuration(FLIP_DURATION)
+ ));
+ mFlipSettingsViewAnim = start(
+ setVisibilityWhenDone(
+ interpolator(mDecelerateInterpolator,
+ ObjectAnimator.ofFloat(
+ mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h))
+ .setDuration(FLIP_DURATION),
+ mFlipSettingsView, View.INVISIBLE));
+ } else {
+ mStackScroller.setTranslationY(0);
+ mFlipSettingsView.setTranslationY(-h);
+ mFlipSettingsView.setVisibility(View.INVISIBLE);
+ }
+ mHeaderFlipper.flipToNotifications(animate);
+ mKeyguardFlipper.flipToNotifications(animate);
mClearButton.setVisibility(View.VISIBLE);
mClearButton.setAlpha(0f);
setAreThereNotifications(); // this will show/hide the button as necessary
@@ -1798,7 +1772,7 @@
public void run() {
updateCarrierLabelVisibility(false);
}
- }, FLIP_DURATION - 150);
+ }, animate ? FLIP_DURATION - 150 : 0);
if (mOnFlipRunnable != null) {
mOnFlipRunnable.run();
}
@@ -1814,14 +1788,10 @@
// Settings are not available in setup
if (!mUserSetup) return;
- if (mHasFlipSettings) {
- mNotificationPanel.expand();
- if (mFlipSettingsView.getVisibility() != View.VISIBLE
- || mFlipSettingsView.getTranslationY() < 0) {
- flipToSettings();
- }
- } else if (mSettingsPanel != null) {
- mSettingsPanel.expand();
+ mNotificationPanel.expand();
+ if (mFlipSettingsView.getVisibility() != View.VISIBLE
+ || mFlipSettingsView.getTranslationY() < 0) {
+ flipToSettings(true /*animate*/);
}
if (false) postStartTracing();
@@ -1834,60 +1804,63 @@
return false;
}
- public void flipToSettings() {
+ public void flipToSettings(boolean animate) {
// Settings are not available in setup
if (!mUserSetup) return;
- if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
- if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ cancelAnim(mFlipSettingsViewAnim);
+ cancelAnim(mScrollViewAnim);
mHeaderFlipper.cancel();
mKeyguardFlipper.cancel();
- if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+ cancelAnim(mClearButtonAnim);
mFlipSettingsView.setVisibility(View.VISIBLE);
final int h = mNotificationPanel.getMeasuredHeight();
- final float settingsY = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h;
- final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0;
- mFlipSettingsViewAnim = start(
- startDelay(0,
+ if (animate) {
+ final float settingsY
+ = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h;
+ final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0;
+ mFlipSettingsViewAnim = start(
+ startDelay(0,
+ interpolator(mDecelerateInterpolator,
+ ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y,
+ settingsY, 0f)
+ .setDuration(FLIP_DURATION)
+ )));
+ mScrollViewAnim = start(
+ setVisibilityWhenDone(
interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y, settingsY, 0f)
- .setDuration(FLIP_DURATION)
- )));
- mScrollViewAnim = start(
- setVisibilityWhenDone(
- interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h)
- )
+ ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h)
+ )
+ .setDuration(FLIP_DURATION),
+ mStackScroller, View.INVISIBLE));
+ } else {
+ mFlipSettingsView.setTranslationY(0);
+ mStackScroller.setTranslationY(h);
+ mStackScroller.setVisibility(View.INVISIBLE);
+ }
+ mHeaderFlipper.flipToSettings(animate);
+ mKeyguardFlipper.flipToSettings(animate);
+ if (animate) {
+ mClearButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
.setDuration(FLIP_DURATION),
- mStackScroller, View.INVISIBLE));
- mHeaderFlipper.flipToSettings();
- mKeyguardFlipper.flipToSettings();
- mClearButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mClearButton, View.INVISIBLE));
+ mClearButton, View.INVISIBLE));
+ } else {
+ mClearButton.setAlpha(0);
+ mClearButton.setVisibility(View.INVISIBLE);
+ }
mNotificationPanel.postDelayed(new Runnable() {
public void run() {
updateCarrierLabelVisibility(false);
}
- }, FLIP_DURATION - 150);
+ }, animate ? FLIP_DURATION - 150 : 0);
if (mOnFlipRunnable != null) {
mOnFlipRunnable.run();
}
}
- public void flipPanels() {
- if (mHasFlipSettings) {
- if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
- flipToSettings();
- } else {
- flipToNotifications();
- }
- }
- }
-
public void animateCollapseQuickSettings() {
mStatusBarView.collapseAllPanels(true);
}
@@ -1907,21 +1880,19 @@
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mStatusBarView.collapseAllPanels(/*animate=*/ false);
- if (mHasFlipSettings) {
- // reset things to their proper state
- if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
- if (mScrollViewAnim != null) mScrollViewAnim.cancel();
- if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+ // reset things to their proper state
+ if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+ if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+ if (mClearButtonAnim != null) mClearButtonAnim.cancel();
- mStackScroller.setVisibility(View.VISIBLE);
- mNotificationPanel.setVisibility(View.GONE);
- mFlipSettingsView.setVisibility(View.GONE);
+ mStackScroller.setVisibility(View.VISIBLE);
+ mNotificationPanel.setVisibility(View.GONE);
+ mFlipSettingsView.setVisibility(View.GONE);
- setAreThereNotifications(); // show the clear button
+ setAreThereNotifications(); // show the clear button
- mHeaderFlipper.reset();
- mKeyguardFlipper.reset();
- }
+ mHeaderFlipper.reset();
+ mKeyguardFlipper.reset();
mExpandedVisible = false;
if (mNavigationBarView != null)
@@ -2111,7 +2082,8 @@
private void checkBarModes() {
if (mDemoMode) return;
int sbMode = mStatusBarMode;
- if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0) {
+ if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0
+ && !mOnKeyguard) {
// if panels are expandable, force the status bar opaque on any interaction
sbMode = MODE_OPAQUE;
}
@@ -2366,12 +2338,6 @@
pw.print (" ");
mNotificationPanel.dump(fd, pw, args);
}
- if (mSettingsPanel != null) {
- pw.println(" mSettingsPanel=" +
- mSettingsPanel + " params=" + mSettingsPanel.getLayoutParams().debug(""));
- pw.print (" ");
- mSettingsPanel.dump(fd, pw, args);
- }
if (DUMPTRUCK) {
synchronized (mNotificationData) {
@@ -2474,13 +2440,6 @@
lp.setMarginStart(mNotificationPanelMarginPx);
mNotificationPanel.setLayoutParams(lp);
- if (mSettingsPanel != null) {
- lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
- lp.gravity = mSettingsPanelGravity;
- lp.setMarginEnd(mNotificationPanelMarginPx);
- mSettingsPanel.setLayoutParams(lp);
- }
-
if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) {
mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx);
mStackScroller.getLocationOnScreen(mStackScrollerPosition);
@@ -2536,7 +2495,7 @@
private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
public void onClick(View v) {
- if (mHasSettingsPanel) {
+ if (mHasQuickSettings) {
animateExpandSettingsPanel();
} else {
startActivityDismissingKeyguard(
@@ -2734,11 +2693,6 @@
if (mNotificationPanelGravity <= 0) {
mNotificationPanelGravity = Gravity.START | Gravity.TOP;
}
- mSettingsPanelGravity = res.getInteger(R.integer.settings_panel_layout_gravity);
- Log.d(TAG, "mSettingsPanelGravity = " + mSettingsPanelGravity);
- if (mSettingsPanelGravity <= 0) {
- mSettingsPanelGravity = Gravity.END | Gravity.TOP;
- }
mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height);
mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height);
@@ -2967,29 +2921,46 @@
public void showKeyguard() {
mOnKeyguard = true;
+ updateKeyguardState();
instantExpandNotificationsPanel();
- if (isFlippedToSettings()) {
- flipToNotifications();
- }
- mKeyguardStatusView.setVisibility(View.VISIBLE);
- mNotificationPanelHeader.setVisibility(View.GONE);
-
- mKeyguardFlipper.setVisibility(View.VISIBLE);
- mSettingsContainer.setKeyguardShowing(true);
- updateRowStates();
}
public void hideKeyguard() {
mOnKeyguard = false;
- mKeyguardStatusView.setVisibility(View.GONE);
- mNotificationPanelHeader.setVisibility(View.VISIBLE);
-
- mKeyguardFlipper.setVisibility(View.GONE);
- mSettingsContainer.setKeyguardShowing(false);
- updateRowStates();
+ updateKeyguardState();
instantCollapseNotificationPanel();
}
+ private void updatePublicMode() {
+ setLockscreenPublicMode(mOnKeyguard && mStatusBarKeyguardViewManager.isSecure());
+ }
+
+ private void updateKeyguardState() {
+ if (mOnKeyguard) {
+ if (isFlippedToSettings()) {
+ flipToNotifications(false /*animate*/);
+ }
+ mKeyguardStatusView.setVisibility(View.VISIBLE);
+ mKeyguardBottomArea.setVisibility(View.VISIBLE);
+ mNotificationPanelHeader.setVisibility(View.GONE);
+
+ mKeyguardFlipper.setVisibility(View.VISIBLE);
+ mSettingsContainer.setKeyguardShowing(true);
+ } else {
+ mKeyguardStatusView.setVisibility(View.GONE);
+ mKeyguardBottomArea.setVisibility(View.GONE);
+ mNotificationPanelHeader.setVisibility(View.VISIBLE);
+
+ mKeyguardFlipper.setVisibility(View.GONE);
+ mSettingsContainer.setKeyguardShowing(false);
+ }
+
+ updatePublicMode();
+ updateRowStates();
+ checkBarModes();
+ updateNotificationIcons();
+ }
+
public void userActivity() {
if (mOnKeyguard) {
mKeyguardViewMediatorCallback.userActivity();
@@ -3016,8 +2987,14 @@
}
private void instantExpandNotificationsPanel() {
- mExpandedVisible = true;
- mNotificationPanel.setExpandedFraction(1);
+ mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ mNotificationPanel.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ mNotificationPanel.setExpandedFraction(1);
+ }
+ });
}
private void instantCollapseNotificationPanel() {
@@ -3035,16 +3012,16 @@
return mKeyguardMaxNotificationCount;
}
+ public NavigationBarView getNavigationBarView() {
+ return mNavigationBarView;
+ }
+
/**
* @return a ViewGroup that spans the entire panel which contains the quick settings
*/
public ViewGroup getQuickSettingsOverlayParent() {
- if (mHasSettingsPanel) {
- if (mHasFlipSettings) {
- return mNotificationPanel;
- } else {
- return mSettingsPanel;
- }
+ if (mHasQuickSettings) {
+ return mNotificationPanel;
} else {
return null;
}
@@ -3070,7 +3047,7 @@
mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button);
if (mSettingsButton != null) {
mSettingsButton.setOnClickListener(mSettingsButtonListener);
- if (mHasSettingsPanel) {
+ if (mHasQuickSettings) {
// the settings panel is hiding behind this button
mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
mSettingsButton.setVisibility(View.VISIBLE);
@@ -3080,11 +3057,9 @@
mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
}
}
- if (mHasFlipSettings) {
- mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button);
- if (mNotificationButton != null) {
- mNotificationButton.setOnClickListener(mNotificationButtonListener);
- }
+ mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button);
+ if (mNotificationButton != null) {
+ mNotificationButton.setOnClickListener(mNotificationButtonListener);
}
}
@@ -3099,7 +3074,7 @@
}
public void userSetup(boolean userSetup) {
- if (mSettingsButton != null && mHasFlipSettings) {
+ if (mSettingsButton != null) {
mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
}
}
@@ -3124,34 +3099,48 @@
}
}
- public void flipToSettings() {
- mSettingsButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mStackScroller, View.INVISIBLE));
+ public void flipToSettings(boolean animate) {
mNotificationButton.setVisibility(View.VISIBLE);
- mNotificationButtonAnim = start(
- ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
- .setDuration(FLIP_DURATION));
+ if (animate) {
+ mSettingsButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+ .setDuration(FLIP_DURATION_OUT),
+ mStackScroller, View.INVISIBLE));
+ mNotificationButtonAnim = start(
+ startDelay(FLIP_DURATION_OUT,
+ ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
+ .setDuration(FLIP_DURATION_IN)));
+ } else {
+ mSettingsButton.setAlpha(0f);
+ mSettingsButton.setVisibility(View.INVISIBLE);
+ mNotificationButton.setAlpha(1f);
+ }
}
- public void flipToNotifications() {
- mNotificationButtonAnim = start(
- setVisibilityWhenDone(
- ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
- .setDuration(FLIP_DURATION),
- mNotificationButton, View.INVISIBLE));
-
+ public void flipToNotifications(boolean animate) {
mSettingsButton.setVisibility(View.VISIBLE);
- mSettingsButtonAnim = start(
- ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
- .setDuration(FLIP_DURATION));
+ if (animate) {
+ mNotificationButtonAnim = start(
+ setVisibilityWhenDone(
+ ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
+ .setDuration(FLIP_DURATION_OUT),
+ mNotificationButton, View.INVISIBLE));
+
+ mSettingsButtonAnim = start(
+ startDelay(FLIP_DURATION_OUT,
+ ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
+ .setDuration(FLIP_DURATION_IN)));
+ } else {
+ mNotificationButton.setVisibility(View.INVISIBLE);
+ mNotificationButton.setAlpha(0f);
+ mSettingsButton.setAlpha(1f);
+ }
}
public void cancel() {
- if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
- if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
+ cancelAnim(mSettingsButtonAnim);
+ cancelAnim(mNotificationButtonAnim);
}
public void setVisibility(int vis) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 583fc3e..6ba18b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -38,13 +38,10 @@
PhoneStatusBar mBar;
int mScrimColor;
int mScrimColorKeyguard;
- float mSettingsPanelDragzoneFrac;
- float mSettingsPanelDragzoneMin;
- boolean mFullWidthNotifications;
PanelView mFadingPanel = null;
PanelView mLastFullyOpenedPanel = null;
- PanelView mNotificationPanel, mSettingsPanel;
+ PanelView mNotificationPanel;
private boolean mShouldFade;
private final PhoneStatusBarTransitions mBarTransitions;
@@ -54,13 +51,6 @@
Resources res = getContext().getResources();
mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
mScrimColorKeyguard = res.getColor(R.color.notification_panel_scrim_color_keyguard);
- mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
- try {
- mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
- } catch (NotFoundException ex) {
- mSettingsPanelDragzoneFrac = 0f;
- }
- mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
mBarTransitions = new PhoneStatusBarTransitions(this);
}
@@ -72,15 +62,8 @@
mBar = bar;
}
- public boolean hasFullWidthNotifications() {
- return mFullWidthNotifications;
- }
-
@Override
public void onAttachedToWindow() {
- for (PanelView pv : mPanels) {
- pv.setRubberbandingEnabled(!mFullWidthNotifications);
- }
mBarTransitions.init();
}
@@ -89,10 +72,7 @@
super.addPanel(pv);
if (pv.getId() == R.id.notification_panel) {
mNotificationPanel = pv;
- } else if (pv.getId() == R.id.settings_panel){
- mSettingsPanel = pv;
}
- pv.setRubberbandingEnabled(!mFullWidthNotifications);
}
@Override
@@ -117,34 +97,10 @@
@Override
public PanelView selectPanelForTouch(MotionEvent touch) {
- final float x = touch.getX();
- final boolean isLayoutRtl = isLayoutRtl();
-
- if (mFullWidthNotifications) {
- // No double swiping. If either panel is open, nothing else can be pulled down.
- return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight())
- + mNotificationPanel.getExpandedHeight() > 0)
- ? null
- : mNotificationPanel;
- }
-
- // We split the status bar into thirds: the left 2/3 are for notifications, and the
- // right 1/3 for quick settings. If you pull the status bar down a second time you'll
- // toggle panels no matter where you pull it down.
-
- final float w = getMeasuredWidth();
- float region = (w * mSettingsPanelDragzoneFrac);
-
- if (DEBUG) {
- Log.v(TAG, String.format(
- "w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
- w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
- }
-
- if (region < mSettingsPanelDragzoneMin) region = mSettingsPanelDragzoneMin;
-
- final boolean showSettings = isLayoutRtl ? (x < region) : (w - region < x);
- return showSettings ? mSettingsPanel : mNotificationPanel;
+ // No double swiping. If either panel is open, nothing else can be pulled down.
+ return mNotificationPanel.getExpandedHeight() > 0
+ ? null
+ : mNotificationPanel;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index b3fba76..f3ebf1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -280,6 +280,7 @@
addUserTiles(mContainerView, inflater);
addSystemTiles(mContainerView, inflater);
addTemporaryTiles(mContainerView, inflater);
+ addAccessibilityTiles(mContainerView);
queryForUserInformation();
queryForSslCaCerts();
@@ -311,6 +312,34 @@
collapsePanels();
}
+ private void addAccessibilityTiles(ViewGroup parent) {
+ if (!DEBUG_GONE_TILES && !SHOW_ACCESSIBILITY_TILES) return;
+
+ // Color inversion tile
+ final SystemSettingTile inversionTile = new SystemSettingTile(mContext);
+ inversionTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+ SystemSettingTile.TYPE_SECURE);
+ inversionTile.setFragment("Settings$AccessibilityInversionSettingsActivity");
+ mModel.addInversionTile(inversionTile, inversionTile.getRefreshCallback());
+ parent.addView(inversionTile);
+
+ // Contrast enhancement tile
+ final SystemSettingTile contrastTile = new SystemSettingTile(mContext);
+ contrastTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
+ SystemSettingTile.TYPE_SECURE);
+ contrastTile.setFragment("Settings$AccessibilityContrastSettingsActivity");
+ mModel.addContrastTile(contrastTile, contrastTile.getRefreshCallback());
+ parent.addView(contrastTile);
+
+ // Color space adjustment tile
+ final SystemSettingTile colorSpaceTile = new SystemSettingTile(mContext);
+ colorSpaceTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+ SystemSettingTile.TYPE_SECURE);
+ colorSpaceTile.setFragment("Settings$AccessibilityDaltonizerSettingsActivity");
+ mModel.addColorSpaceTile(colorSpaceTile, colorSpaceTile.getRefreshCallback());
+ parent.addView(colorSpaceTile);
+ }
+
private void addUserTiles(final ViewGroup parent, final LayoutInflater inflater) {
QuickSettingsTileView userTile = (QuickSettingsTileView)
inflater.inflate(R.layout.quick_settings_tile, parent, false);
@@ -384,35 +413,6 @@
new QuickSettingsModel.BasicRefreshCallback(settingsTile));
parent.addView(settingsTile);
mDynamicSpannedTiles.add(settingsTile);
-
- if (SHOW_ACCESSIBILITY_TILES) {
- // Color inversion tile
- final SystemSettingTile inversionTile = new SystemSettingTile(mContext);
- inversionTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
- SystemSettingTile.TYPE_SECURE);
- inversionTile.setFragment("Settings$AccessibilityInversionSettingsActivity");
- mModel.addInversionTile(inversionTile, inversionTile.getRefreshCallback());
- parent.addView(inversionTile);
- mDynamicSpannedTiles.add(inversionTile);
-
- // Contrast enhancement tile
- final SystemSettingTile contrastTile = new SystemSettingTile(mContext);
- contrastTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
- SystemSettingTile.TYPE_SECURE);
- contrastTile.setFragment("Settings$AccessibilityContrastSettingsActivity");
- mModel.addContrastTile(contrastTile, contrastTile.getRefreshCallback());
- parent.addView(contrastTile);
- mDynamicSpannedTiles.add(contrastTile);
-
- // Color space adjustment tile
- final SystemSettingTile colorSpaceTile = new SystemSettingTile(mContext);
- colorSpaceTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
- SystemSettingTile.TYPE_SECURE);
- colorSpaceTile.setFragment("Settings$AccessibilityDaltonizerSettingsActivity");
- mModel.addColorSpaceTile(colorSpaceTile, colorSpaceTile.getRefreshCallback());
- parent.addView(colorSpaceTile);
- mDynamicSpannedTiles.add(colorSpaceTile);
- }
}
private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
@@ -574,49 +574,6 @@
});
parent.addView(batteryTile);
- // Airplane Mode
- final QuickSettingsBasicTile airplaneTile
- = new QuickSettingsBasicTile(mContext);
- mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
- @Override
- public void refreshView(QuickSettingsTileView unused, State state) {
- airplaneTile.setImageResource(state.iconId);
-
- String airplaneState = mContext.getString(
- (state.enabled) ? R.string.accessibility_desc_on
- : R.string.accessibility_desc_off);
- airplaneTile.setContentDescription(
- mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
- airplaneTile.setText(state.label);
- }
- });
- parent.addView(airplaneTile);
-
- // Zen Mode
- final QuickSettingsBasicTile zenModeTile = new QuickSettingsBasicTile(mContext);
- zenModeTile.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- showZenModeDialog();
- }
- });
- mModel.addZenModeTile(zenModeTile, new QuickSettingsModel.RefreshCallback() {
- @Override
- public void refreshView(QuickSettingsTileView unused, State state) {
- zenModeTile.setImageResource(state.iconId);
- // TODO cut new assets
- zenModeTile.getImageView().setAlpha(state.enabled ? 1 : .2f);
- zenModeTile.getImageView().setScaleX(1.5f);
- zenModeTile.getImageView().setScaleY(1.5f);
- // for landscape version
- zenModeTile.getTextView().setMaxLines(2);
- zenModeTile.getTextView().setEllipsize(TruncateAt.END);
- // TODO content description
- zenModeTile.setText(state.label);
- }
- });
- parent.addView(zenModeTile);
-
// Bluetooth
if (mModel.deviceSupportsBluetooth()
|| DEBUG_GONE_TILES) {
@@ -710,6 +667,50 @@
}
});
parent.addView(locationTile);
+
+ // Airplane Mode
+ final QuickSettingsBasicTile airplaneTile
+ = new QuickSettingsBasicTile(mContext);
+ mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
+ @Override
+ public void refreshView(QuickSettingsTileView unused, State state) {
+ airplaneTile.setImageResource(state.iconId);
+
+ String airplaneState = mContext.getString(
+ (state.enabled) ? R.string.accessibility_desc_on
+ : R.string.accessibility_desc_off);
+ airplaneTile.setContentDescription(
+ mContext.getString(R.string.accessibility_quick_settings_airplane,
+ airplaneState));
+ airplaneTile.setText(state.label);
+ }
+ });
+ parent.addView(airplaneTile);
+
+ // Zen Mode
+ final QuickSettingsBasicTile zenModeTile = new QuickSettingsBasicTile(mContext);
+ zenModeTile.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showZenModeDialog();
+ }
+ });
+ mModel.addZenModeTile(zenModeTile, new QuickSettingsModel.RefreshCallback() {
+ @Override
+ public void refreshView(QuickSettingsTileView unused, State state) {
+ zenModeTile.setImageResource(state.iconId);
+ // TODO cut new assets
+ zenModeTile.getImageView().setAlpha(state.enabled ? 1 : .2f);
+ zenModeTile.getImageView().setScaleX(1.5f);
+ zenModeTile.getImageView().setScaleY(1.5f);
+ // for landscape version
+ zenModeTile.getTextView().setMaxLines(2);
+ zenModeTile.getTextView().setEllipsize(TruncateAt.END);
+ // TODO content description
+ zenModeTile.setText(state.label);
+ }
+ });
+ parent.addView(zenModeTile);
}
private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
index 02e9c0d..c44cb0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
@@ -62,18 +62,19 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mScrim = new ScrimView(mContext);
- addView(mScrim);
- mScrim.setAlpha(sShowScrim ? 1 : 0);
+ if (sShowScrim) {
+ mScrim = new ScrimView(mContext);
+ addView(mScrim);
+ }
// TODO: Setup the layout transitions
LayoutTransition transitions = getLayoutTransition();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mScrim.getAlpha() == 1) {
- mScrim.animate().alpha(0).setDuration(1000).start();
+ if (mScrim != null) {
sShowScrim = false;
+ removeView(mScrim);
}
return super.onTouchEvent(event);
}
@@ -144,7 +145,9 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- mScrim.bringToFront();
+ if (mScrim != null) {
+ mScrim.bringToFront();
+ }
final int N = getChildCount();
final boolean isLayoutRtl = isLayoutRtl();
final int width = getWidth();
@@ -206,6 +209,7 @@
}
private static final class ScrimView extends View {
+ private static final int SCRIM = 0x4f000000;
private static final int COLOR = 0xaf4285f4;
private final Paint mLinePaint;
@@ -240,6 +244,7 @@
final int h = getMeasuredHeight();
final int f = mStrokeWidth * 3 / 4;
+ canvas.drawColor(SCRIM);
canvas.drawPath(line(f, h / 2, w - f, h / 2), mLinePaint);
canvas.drawPath(line(w / 2, f, w / 2, h - f), mLinePaint);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 9b25046..e1ef83a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -608,7 +608,7 @@
Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
mZenModeState.enabled = mode != Settings.Global.ZEN_MODE_OFF;
mZenModeState.zenMode = mode;
- mZenModeState.label = ZenModeView.MODE_LABEL;
+ mZenModeState.label = mContext.getString(R.string.zen_mode_title);
mZenModeState.iconId = R.drawable.stat_sys_zen_limited;
mZenModeCallback.refreshView(mZenModeTile, mZenModeState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
deleted file mode 100644
index c10a0d4..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.EventLog;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-
-import com.android.systemui.EventLogTags;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.GestureRecorder;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-
-public class SettingsPanelView extends PanelView {
- public static final boolean DEBUG_GESTURES = true;
-
- private QuickSettings mQS;
- private QuickSettingsContainerView mQSContainer;
-
- Drawable mHandleBar;
- int mHandleBarHeight;
- View mHandleView;
-
- public SettingsPanelView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mQSContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
-
- Resources resources = getContext().getResources();
- mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
- mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
- mHandleView = findViewById(R.id.handle);
- }
-
- public void setQuickSettings(QuickSettings qs) {
- mQS = qs;
- }
-
- @Override
- public void setBar(PanelBar panelBar) {
- super.setBar(panelBar);
-
- if (mQS != null) {
- mQS.setBar(panelBar);
- }
- }
-
- public void setImeWindowStatus(boolean visible) {
- if (mQS != null) {
- mQS.setImeWindowStatus(visible);
- }
- }
-
- public void setup(NetworkController networkController, BluetoothController bluetoothController,
- BatteryController batteryController, LocationController locationController,
- RotationLockController rotationLockController) {
- if (mQS != null) {
- mQS.setup(networkController, bluetoothController, batteryController,
- locationController, rotationLockController);
- }
- }
-
- void updateResources() {
- if (mQS != null) {
- mQS.updateResources();
- }
- if (mQSContainer != null) {
- mQSContainer.updateResources();
- }
- requestLayout();
- }
-
- @Override
- public void fling(float vel, boolean always) {
- GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
- if (gr != null) {
- gr.tag(
- "fling " + ((vel > 0) ? "open" : "closed"),
- "settings,v=" + vel);
- }
- super.fling(vel, always);
- }
-
- public void setService(PhoneStatusBar phoneStatusBar) {
- if (mQS != null) {
- mQS.setService(phoneStatusBar);
- }
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
- event.getText()
- .add(getContext().getString(R.string.accessibility_desc_quick_settings));
- return true;
- }
-
- return super.dispatchPopulateAccessibilityEvent(event);
- }
-
- // We draw the handle ourselves so that it's always glued to the bottom of the window.
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed) {
- final int pl = getPaddingLeft();
- final int pr = getPaddingRight();
- mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
- canvas.translate(0, off);
- mHandleBar.setState(mHandleView.getDrawableState());
- mHandleBar.draw(canvas);
- canvas.translate(0, -off);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (DEBUG_GESTURES) {
- if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
- EventLog.writeEvent(EventLogTags.SYSUI_QUICKPANEL_TOUCH,
- event.getActionMasked(), (int) event.getX(), (int) event.getY());
- }
- }
- return super.onTouchEvent(event);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 41b5b7c..c2595cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -56,6 +56,7 @@
private boolean mScreenOn = false;
private KeyguardBouncer mBouncer;
private boolean mShowing;
+ private boolean mOccluded;
public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils) {
@@ -152,7 +153,9 @@
}
public void setOccluded(boolean occluded) {
+ mOccluded = occluded;
mStatusBarWindowManager.setKeyguardOccluded(occluded);
+ updateBackButtonState();
}
/**
@@ -164,6 +167,7 @@
mStatusBarWindowManager.setKeyguardShowing(false);
mBouncer.hide();
mViewMediatorCallback.keyguardGone();
+ updateBackButtonState();
}
/**
@@ -175,6 +179,10 @@
}
}
+ public boolean isSecure() {
+ return mBouncer.isSecure();
+ }
+
/**
* @return Whether the keyguard is showing
*/
@@ -205,6 +213,11 @@
} else {
mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
}
+ if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
+ mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
+ } else {
+ mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+ }
}
public boolean onMenuPressed() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1d675bd..c5dae85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -52,6 +53,16 @@
}
@Override
+ protected boolean fitSystemWindows(Rect insets) {
+ if (getFitsSystemWindows()) {
+ setPadding(insets.left, insets.top, insets.right, insets.bottom);
+ } else {
+ setPadding(0, 0, 0, 0);
+ }
+ return true;
+ }
+
+ @Override
protected void onAttachedToWindow () {
super.onAttachedToWindow();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index 49cf78b..c1662ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -42,13 +42,13 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.android.systemui.R;
import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
public class ZenModeView extends RelativeLayout {
private static final String TAG = ZenModeView.class.getSimpleName();
private static final boolean DEBUG = false;
- public static final String MODE_LABEL = "Limited interruptions";
public static final int BACKGROUND = 0xff282828;
private static final Typeface CONDENSED =
@@ -91,7 +91,7 @@
LayoutParams lp = null;
mModeText = new TextView(mContext);
- mModeText.setText(MODE_LABEL);
+ mModeText.setText(R.string.zen_mode_title);
mModeText.setId(android.R.id.title);
mModeText.setTextColor(GRAY);
mModeText.setTypeface(CONDENSED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 9800bc9..36d94a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -20,7 +20,6 @@
import android.content.res.Configuration;
import android.graphics.Canvas;
-import android.graphics.Outline;
import android.graphics.Paint;
import android.util.AttributeSet;
@@ -31,6 +30,7 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.OverScroller;
import com.android.systemui.ExpandHelper;
@@ -55,7 +55,7 @@
private static final int INVALID_POINTER = -1;
private SwipeHelper mSwipeHelper;
- private boolean mSwipingInProgress = true;
+ private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
private int mOwnScrollY;
private int mMaxLayoutHeight;
@@ -73,7 +73,6 @@
private int mSidePaddings;
private Paint mDebugPaint;
- private int mBackgroundRoundedRectCornerRadius;
private int mContentHeight;
private int mCollapsedSize;
private int mBottomStackPeekSize;
@@ -145,9 +144,6 @@
mSidePaddings = context.getResources()
.getDimensionPixelSize(R.dimen.notification_side_padding);
- mBackgroundRoundedRectCornerRadius = context.getResources()
- .getDimensionPixelSize(
- com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
mCollapsedSize = context.getResources()
.getDimensionPixelSize(R.dimen.notification_row_min_height);
mBottomStackPeekSize = context.getResources()
@@ -177,18 +173,23 @@
View child = getChildAt(i);
float width = child.getMeasuredWidth();
float height = child.getMeasuredHeight();
- int oldWidth = child.getWidth();
- int oldHeight = child.getHeight();
child.layout((int) (centerX - width / 2.0f),
0,
(int) (centerX + width / 2.0f),
(int) height);
- updateChildOutline(child, width, height, oldWidth, oldHeight);
}
setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
- updateScrollPositionIfNecessary();
- updateChildren();
updateContentHeight();
+ getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ updateScrollPositionIfNecessary();
+ updateChildren();
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
+
}
public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
@@ -227,7 +228,6 @@
mCurrentStackScrollState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
mCurrentStackScrollState.apply();
- mOwnScrollY = mCurrentStackScrollState.getScrollY();
if (mListener != null) {
mListener.onChildLocationsChanged(this);
}
@@ -240,31 +240,6 @@
return false;
}
- private void updateChildOutline(View child,
- float width,
- float height,
- int oldWidth,
- int oldHeight) {
- // The children currently have paddings inside themselfs because of the expansion
- // visualization. In order for the shadows to work correctly we have to set the correct
- // outline.
- View container = child.findViewById(R.id.container);
- if (container != null && (oldWidth != width || oldHeight != height)) {
- Outline outline = getOutlineForSize(container.getLeft(),
- container.getTop(),
- container.getWidth(),
- container.getHeight());
- child.setOutline(outline);
- }
- }
-
- private Outline getOutlineForSize(int leftInset, int topInset, int width, int height) {
- Outline result = new Outline();
- result.setRoundRect(leftInset, topInset, leftInset + width, topInset + height,
- mBackgroundRoundedRectCornerRadius);
- return result;
- }
-
private void updateScrollPositionIfNecessary() {
int scrollRange = getScrollRange();
if (scrollRange < mOwnScrollY) {
@@ -284,7 +259,7 @@
*
* @return either the layout height or the externally defined height, whichever is smaller
*/
- private float getLayoutHeight() {
+ private int getLayoutHeight() {
return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
}
@@ -640,14 +615,48 @@
private int getScrollRange() {
int scrollRange = 0;
- if (getChildCount() > 0) {
+ View firstChild = getFirstChildNotGone();
+ if (firstChild != null) {
int contentHeight = getContentHeight();
- scrollRange = Math.max(0,
- contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+ int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
+ int firstChildExpandPotential = firstChildMaxExpandHeight - firstChild.getHeight();
+
+ // If we already scrolled in, the first child is layouted smaller than it actually
+ // could be when expanded. We have to compensate for this loss of the contentHeight
+ // by adding the expand potential again.
+ contentHeight += firstChildExpandPotential;
+ scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+ if (scrollRange > 0 && getChildCount() > 0) {
+ // We want to at least be able collapse the first item and not ending in a weird
+ // end state.
+ scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight - mCollapsedSize);
+ }
}
return scrollRange;
}
+ /**
+ * @return the first child which has visibility unequal to GONE
+ */
+ private View getFirstChildNotGone() {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() != View.GONE) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ private int getMaxExpandHeight(View view) {
+ if (view instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ return row.getMaximumAllowedExpandHeight();
+ }
+ return view.getHeight();
+ }
+
private int getContentHeight() {
return mContentHeight;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 431f6fe..d9e7f66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -20,6 +20,7 @@
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -47,13 +48,14 @@
private StackIndentationFunctor mTopStackIndentationFunctor;
private StackIndentationFunctor mBottomStackIndentationFunctor;
- private float mLayoutHeight;
+ private int mLayoutHeight;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
private boolean mIsExpansionChanging;
private int mFirstChildMaxHeight;
private boolean mIsExpanded;
private View mFirstChildWhileExpanding;
private boolean mExpandedOnStart;
+ private int mTopStackTotalSize;
public StackScrollAlgorithm(Context context) {
initConstants(context);
@@ -72,16 +74,16 @@
mZDistanceBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.z_distance_between_notifications);
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
-
+ mTopStackTotalSize = mCollapsedSize + mPaddingBetweenElements;
mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_TOP_STACK,
mTopStackPeekSize,
- mCollapsedSize + mPaddingBetweenElements,
+ mTopStackTotalSize,
0.5f);
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_BOTTOM_STACK,
mBottomStackPeekSize,
- mBottomStackPeekSize,
+ mCollapsedSize + mPaddingBetweenElements + mBottomStackPeekSize,
0.5f);
}
@@ -94,14 +96,17 @@
// First we reset the view states to their default values.
resultState.resetViewStates();
- // The first element is always in there so it's initialized with 1.0f;
- algorithmState.itemsInTopStack = 1.0f;
+ algorithmState.itemsInTopStack = 0.0f;
algorithmState.partialInTop = 0.0f;
algorithmState.lastTopStackIndex = 0;
- algorithmState.scrollY = resultState.getScrollY();
+ algorithmState.scrolledPixelsTop = 0;
algorithmState.itemsInBottomStack = 0.0f;
+ algorithmState.partialInBottom = 0.0f;
+
updateVisibleChildren(resultState, algorithmState);
+ algorithmState.scrollY = getAlgorithmScrollPosition(resultState, algorithmState);
+
// Phase 1:
findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
@@ -110,9 +115,42 @@
// Phase 3:
updateZValuesForState(resultState, algorithmState);
+ }
- // write the algorithm state to the result
- resultState.setScrollY(algorithmState.scrollY);
+ /**
+ * Calculates the scroll offset of the algorithm, based on the resultState.
+ *
+ * @param resultState the state to base the calculation on
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ * @return the scroll offset used for the algorithm
+ */
+ private int getAlgorithmScrollPosition(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+
+ int resultScroll = resultState.getScrollY() + mCollapsedSize;
+
+ // If the first child was collapsed in an earlier pass, we have to decrease the scroll
+ // position to get into the same state again.
+ if (algorithmState.visibleChildren.size() > 0) {
+ View firstView = algorithmState.visibleChildren.get(0);
+ if (firstView instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow firstRow = (ExpandableNotificationRow) firstView;
+ if (firstRow.isUserLocked()) {
+ // User is currently modifying this height.
+ return resultScroll;
+ }
+ int scrolledInAmount = 0;
+ // If the child size was not decreased due to scrolling, we don't substract it,
+ if (!mIsExpansionChanging) {
+ scrolledInAmount = firstRow.getExpandPotential();
+ } else if (mExpandedOnStart && mFirstChildWhileExpanding == firstView) {
+ scrolledInAmount = firstRow.getMaximumAllowedExpandHeight() -
+ mFirstChildMaxHeight;
+ }
+ resultScroll -= scrolledInAmount;
+ }
+ }
+ return resultScroll;
}
/**
@@ -141,13 +179,12 @@
*/
private void updatePositionsForState(StackScrollState resultState,
StackScrollAlgorithmState algorithmState) {
- float stackHeight = getLayoutHeight();
// The starting position of the bottom stack peek
- float bottomPeekStart = stackHeight - mBottomStackPeekSize;
+ float bottomPeekStart = mLayoutHeight - mBottomStackPeekSize;
// The position where the bottom stack starts.
- float transitioningPositionStart = bottomPeekStart - mCollapsedSize;
+ float bottomStackStart = bottomPeekStart - mCollapsedSize;
// The y coordinate of the current child.
float currentYPosition = 0.0f;
@@ -160,76 +197,110 @@
for (int i = 0; i < childCount; i++) {
View child = algorithmState.visibleChildren.get(i);
StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
- childViewState.yTranslation = currentYPosition;
childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
int childHeight = child.getHeight();
- // The y position after this element
- float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
float yPositionInScrollViewAfterElement = yPositionInScrollView
+ childHeight
+ mPaddingBetweenElements;
- float scrollOffset = yPositionInScrollViewAfterElement - algorithmState.scrollY;
- if (i < algorithmState.lastTopStackIndex) {
+ float scrollOffset = yPositionInScrollView - algorithmState.scrollY + mCollapsedSize;
+
+ if (i == algorithmState.lastTopStackIndex + 1) {
+ // Normally the position of this child is the position in the regular scrollview,
+ // but if the two stacks are very close to each other,
+ // then have have to push it even more upwards to the position of the bottom
+ // stack start.
+ currentYPosition = Math.min(scrollOffset, bottomStackStart);
+ }
+ childViewState.yTranslation = currentYPosition;
+
+ // The y position after this element
+ float nextYPosition = currentYPosition + childHeight +
+ mPaddingBetweenElements;
+
+ if (i <= algorithmState.lastTopStackIndex) {
// Case 1:
// We are in the top Stack
- nextYPosition = updateStateForTopStackChild(algorithmState,
- numberOfElementsCompletelyIn,
- i, childViewState);
- } else if (i == algorithmState.lastTopStackIndex) {
+ updateStateForTopStackChild(algorithmState,
+ numberOfElementsCompletelyIn, i, childHeight, childViewState, scrollOffset);
+ clampYTranslation(childViewState, childHeight);
+ // check if we are overlapping with the bottom stack
+ if (childViewState.yTranslation + childHeight + mPaddingBetweenElements
+ >= bottomStackStart && !mIsExpansionChanging) {
+ // TODO: handle overlapping sizes with end stack better
+ // we just collapse this element
+ childViewState.height = mCollapsedSize;
+ }
+ } else if (nextYPosition >= bottomStackStart) {
// Case 2:
- // First element of regular scrollview comes next, so the position is just the
- // scrolling position
- nextYPosition = updateStateForFirstScrollingChild(transitioningPositionStart,
- childViewState, scrollOffset);
- } else if (nextYPosition >= transitioningPositionStart) {
- if (currentYPosition >= transitioningPositionStart) {
- // Case 3:
+ // We are in the bottom stack.
+ if (currentYPosition >= bottomStackStart) {
// According to the regular scroll view we are fully translated out of the
// bottom of the screen so we are fully in the bottom stack
- nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
- transitioningPositionStart, childViewState, childHeight);
+ updateStateForChildFullyInBottomStack(algorithmState,
+ bottomStackStart, childViewState, childHeight);
} else {
- // Case 4:
// According to the regular scroll view we are currently translating out of /
// into the bottom of the screen
- nextYPosition = updateStateForChildTransitioningInBottom(
- algorithmState, stackHeight, transitioningPositionStart,
- currentYPosition, childViewState,
- childHeight, nextYPosition);
+ updateStateForChildTransitioningInBottom(algorithmState,
+ bottomStackStart, bottomPeekStart, currentYPosition,
+ childViewState, childHeight);
}
} else {
+ // Case 3:
+ // We are in the regular scroll area.
childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+ clampYTranslation(childViewState, childHeight);
}
+
// The first card is always rendered.
if (i == 0) {
childViewState.alpha = 1.0f;
+ childViewState.yTranslation = 0;
childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
}
if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) {
Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
}
- nextYPosition = Math.max(0, nextYPosition);
- currentYPosition = nextYPosition;
+ currentYPosition = childViewState.yTranslation + childHeight + mPaddingBetweenElements;
yPositionInScrollView = yPositionInScrollViewAfterElement;
}
}
/**
- * Update the state for the first child which is in the regular scrolling area.
+ * Clamp the yTranslation both up and down to valid positions.
*
- * @param transitioningPositionStart the transition starting position of the bottom stack
* @param childViewState the view state of the child
- * @param scrollOffset the position in the regular scroll view after this child
- * @return the next child position
+ * @param childHeight the height of this child
*/
- private float updateStateForFirstScrollingChild(float transitioningPositionStart,
- StackScrollState.ViewState childViewState, float scrollOffset) {
- childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
- if (scrollOffset < transitioningPositionStart) {
- return scrollOffset;
- } else {
- return transitioningPositionStart;
- }
+ private void clampYTranslation(StackScrollState.ViewState childViewState, int childHeight) {
+ clampPositionToBottomStackStart(childViewState, childHeight);
+ clampPositionToTopStackEnd(childViewState, childHeight);
+ }
+
+ /**
+ * Clamp the yTranslation of the child down such that its end is at most on the beginning of
+ * the bottom stack.
+ *
+ * @param childViewState the view state of the child
+ * @param childHeight the height of this child
+ */
+ private void clampPositionToBottomStackStart(StackScrollState.ViewState childViewState,
+ int childHeight) {
+ childViewState.yTranslation = Math.min(childViewState.yTranslation,
+ mLayoutHeight - mBottomStackPeekSize - childHeight);
+ }
+
+ /**
+ * Clamp the yTranslation of the child up such that its end is at lest on the end of the top
+ * stack.
+ *
+ * @param childViewState the view state of the child
+ * @param childHeight the height of this child
+ */
+ private void clampPositionToTopStackEnd(StackScrollState.ViewState childViewState,
+ int childHeight) {
+ childViewState.yTranslation = Math.max(childViewState.yTranslation,
+ mCollapsedSize - childHeight);
}
private int getMaxAllowedChildHeight(View child) {
@@ -240,41 +311,35 @@
return child.getHeight();
}
- private float updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
- float stackHeight, float transitioningPositionStart, float currentYPosition,
- StackScrollState.ViewState childViewState, int childHeight, float nextYPosition) {
- float newSize = transitioningPositionStart + mCollapsedSize - currentYPosition;
- newSize = Math.min(childHeight, newSize);
- // Transitioning element on top of bottom stack:
- algorithmState.partialInBottom = 1.0f - (
- (stackHeight - mBottomStackPeekSize - nextYPosition) / mCollapsedSize);
- // Our element can be expanded, so we might even have to scroll further than
- // mCollapsedSize
- algorithmState.partialInBottom = Math.min(1.0f, algorithmState.partialInBottom);
- float offset = mBottomStackIndentationFunctor.getValue(
- algorithmState.partialInBottom);
- nextYPosition = transitioningPositionStart + offset;
- algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
- // TODO: only temporarily collapse
- if (childHeight != (int) newSize) {
- childViewState.height = (int) newSize;
- }
- childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+ private void updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
+ float transitioningPositionStart, float bottomPeakStart, float currentYPosition,
+ StackScrollState.ViewState childViewState, int childHeight) {
- return nextYPosition;
+ // This is the transitioning element on top of bottom stack, calculate how far we are in.
+ algorithmState.partialInBottom = 1.0f - (
+ (transitioningPositionStart - currentYPosition) / (childHeight +
+ mPaddingBetweenElements));
+
+ // the offset starting at the transitionPosition of the bottom stack
+ float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
+ algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
+ childViewState.yTranslation = transitioningPositionStart + offset - childHeight;
+
+ // We want at least to be at the end of the top stack when collapsing
+ clampPositionToTopStackEnd(childViewState, childHeight);
+ childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
}
- private float updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
+ private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
float transitioningPositionStart, StackScrollState.ViewState childViewState,
int childHeight) {
- float nextYPosition;
+ float currentYPosition;
algorithmState.itemsInBottomStack += 1.0f;
if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
// We are visually entering the bottom stack
- nextYPosition = transitioningPositionStart
- + mBottomStackIndentationFunctor.getValue(
- algorithmState.itemsInBottomStack);
+ currentYPosition = transitioningPositionStart
+ + mBottomStackIndentationFunctor.getValue(algorithmState.itemsInBottomStack);
childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
} else {
// we are fully inside the stack
@@ -285,43 +350,56 @@
childViewState.alpha = 1.0f - algorithmState.partialInBottom;
}
childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
- nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
+ currentYPosition = mLayoutHeight;
}
- // TODO: only temporarily collapse
- if (childHeight != mCollapsedSize) {
- childViewState.height = mCollapsedSize;
- }
- return nextYPosition;
+ childViewState.yTranslation = currentYPosition - childHeight;
+ clampPositionToTopStackEnd(childViewState, childHeight);
}
- private float updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
- int numberOfElementsCompletelyIn, int i, StackScrollState.ViewState childViewState) {
+ private void updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
+ int numberOfElementsCompletelyIn, int i, int childHeight,
+ StackScrollState.ViewState childViewState, float scrollOffset) {
- float nextYPosition = 0;
// First we calculate the index relative to the current stack window of size at most
// {@link #MAX_ITEMS_IN_TOP_STACK}
- int paddedIndex = i
+ int paddedIndex = i - 1
- Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
if (paddedIndex >= 0) {
+
// We are currently visually entering the top stack
- nextYPosition = mCollapsedSize + mPaddingBetweenElements -
- mTopStackIndentationFunctor.getValue(
- algorithmState.itemsInTopStack - i - 1);
- nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize
- - mBottomStackPeekSize);
- if (paddedIndex == 0) {
- childViewState.alpha = 1.0f - algorithmState.partialInTop;
- childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+ float distanceToStack = childHeight - algorithmState.scrolledPixelsTop;
+ if (i == algorithmState.lastTopStackIndex && distanceToStack > mTopStackTotalSize) {
+
+ // Child is currently translating into stack but not yet inside slow down zone.
+ // Handle it like the regular scrollview.
+ childViewState.yTranslation = scrollOffset;
} else {
- childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+ // Apply stacking logic.
+ float numItemsBefore;
+ if (i == algorithmState.lastTopStackIndex) {
+ numItemsBefore = 1.0f - (distanceToStack / mTopStackTotalSize);
+ } else {
+ numItemsBefore = algorithmState.itemsInTopStack - i;
+ }
+ // The end position of the current child
+ float currentChildEndY = mCollapsedSize + mTopStackTotalSize -
+ mTopStackIndentationFunctor.getValue(numItemsBefore);
+ childViewState.yTranslation = currentChildEndY - childHeight;
}
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
} else {
- // We are hidden behind the top card and faded out, so we can hide ourselves.
- childViewState.alpha = 0.0f;
+ if (paddedIndex == -1) {
+ childViewState.alpha = 1.0f - algorithmState.partialInTop;
+ } else {
+ // We are hidden behind the top card and faded out, so we can hide ourselves.
+ childViewState.alpha = 0.0f;
+ }
+ childViewState.yTranslation = mCollapsedSize - childHeight;
childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
}
- return nextYPosition;
+
+
}
/**
@@ -347,10 +425,22 @@
+ childHeight
+ mPaddingBetweenElements;
if (yPositionInScrollView < algorithmState.scrollY) {
- if (yPositionInScrollViewAfterElement <= algorithmState.scrollY) {
+ if (i == 0 && algorithmState.scrollY == mCollapsedSize) {
+
+ // The starting position of the bottom stack peek
+ int bottomPeekStart = mLayoutHeight - mBottomStackPeekSize;
+ // Collapse and expand the first child while the shade is being expanded
+ float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
+ ? mFirstChildMaxHeight
+ : childHeight;
+ childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+ mCollapsedSize);
+ algorithmState.itemsInTopStack = 1.0f;
+
+ } else if (yPositionInScrollViewAfterElement < algorithmState.scrollY) {
// According to the regular scroll view we are fully off screen
algorithmState.itemsInTopStack += 1.0f;
- if (childHeight != mCollapsedSize) {
+ if (i == 0) {
childViewState.height = mCollapsedSize;
}
} else {
@@ -360,45 +450,27 @@
- mPaddingBetweenElements
- algorithmState.scrollY;
+ if (i == 0) {
+ newSize += mCollapsedSize;
+ }
+
// How much did we scroll into this child
- algorithmState.partialInTop = (mCollapsedSize - newSize) / (mCollapsedSize
+ algorithmState.scrolledPixelsTop = childHeight - newSize;
+ algorithmState.partialInTop = (algorithmState.scrolledPixelsTop) / (childHeight
+ mPaddingBetweenElements);
// Our element can be expanded, so this can get negative
algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
algorithmState.itemsInTopStack += algorithmState.partialInTop;
- // TODO: handle overlapping sizes with end stack
newSize = Math.max(mCollapsedSize, newSize);
- // TODO: only temporarily collapse
- if (newSize != childHeight) {
+ if (i == 0) {
childViewState.height = (int) newSize;
-
- // We decrease scrollY by the same amount we made this child smaller.
- // The new scroll position is therefore the start of the element
- algorithmState.scrollY = (int) yPositionInScrollView;
- resultState.setScrollY(algorithmState.scrollY);
}
- if (childHeight > mCollapsedSize) {
- // If we are just resizing this child, this element is not treated to be
- // transitioning into the stack and therefore it is the last element in
- // the stack.
- algorithmState.lastTopStackIndex = i;
- break;
- }
+ algorithmState.lastTopStackIndex = i;
+ break;
}
} else {
- algorithmState.lastTopStackIndex = i;
- if (i == 0) {
-
- // The starting position of the bottom stack peek
- float bottomPeekStart = getLayoutHeight() - mBottomStackPeekSize;
- // Collapse and expand the first child while the shade is being expanded
- float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
- ? mFirstChildMaxHeight
- : childHeight;
- childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
- mCollapsedSize);
- }
+ algorithmState.lastTopStackIndex = i - 1;
// We are already past the stack so we can end the loop
break;
}
@@ -435,11 +507,11 @@
}
}
- public float getLayoutHeight() {
+ public int getLayoutHeight() {
return mLayoutHeight;
}
- public void setLayoutHeight(float layoutHeight) {
+ public void setLayoutHeight(int layoutHeight) {
this.mLayoutHeight = layoutHeight;
}
@@ -461,7 +533,23 @@
} else {
// We are expanding the shade, expand it to its full height.
- mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
+ if (mFirstChildWhileExpanding.getWidth() == 0) {
+
+ // This child was not layouted yet, wait for a layout pass
+ mFirstChildWhileExpanding
+ .addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right,
+ int bottom, int oldLeft, int oldTop, int oldRight,
+ int oldBottom) {
+ mFirstChildMaxHeight = getMaxAllowedChildHeight(
+ mFirstChildWhileExpanding);
+ mFirstChildWhileExpanding.removeOnLayoutChangeListener(this);
+ }
+ });
+ } else {
+ mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
+ }
}
} else {
mFirstChildMaxHeight = 0;
@@ -512,10 +600,12 @@
public float partialInTop;
/**
+ * The number of pixels the last child in the top stack has scrolled in to the stack
+ */
+ public float scrolledPixelsTop;
+
+ /**
* The last item index which is in the top stack.
- * NOTE: In the top stack the item after the transitioning element is also in the stack!
- * This is needed to ensure a smooth transition between the y position in the regular
- * scrollview and the one in the stack.
*/
public int lastTopStackIndex;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 06a08f3..9742e65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -16,10 +16,14 @@
package com.android.systemui.statusbar.stack;
+import android.graphics.Outline;
+import android.graphics.Rect;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import com.android.systemui.R;
+
import java.util.HashMap;
import java.util.Map;
@@ -34,6 +38,10 @@
private final ViewGroup mHostView;
private Map<View, ViewState> mStateMap;
private int mScrollY;
+ private final Rect mClipRect = new Rect();
+ private int mBackgroundRoundedRectCornerRadius;
+ private final Outline mChildOutline = new Outline();
+ private final int mChildDividerHeight;
public int getScrollY() {
return mScrollY;
@@ -46,6 +54,10 @@
public StackScrollState(ViewGroup hostView) {
mHostView = hostView;
mStateMap = new HashMap<View, ViewState>();
+ mBackgroundRoundedRectCornerRadius = hostView.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
+ mChildDividerHeight = hostView.getResources().getDimensionPixelSize(R.dimen
+ .notification_divider_height);
}
public ViewGroup getHostView() {
@@ -83,10 +95,17 @@
*/
public void apply() {
int numChildren = mHostView.getChildCount();
+ float previousNotificationEnd = 0;
+ float previousNotificationStart = 0;
for (int i = 0; i < numChildren; i++) {
View child = mHostView.getChildAt(i);
ViewState state = mStateMap.get(child);
- if (state != null) {
+ if (state == null) {
+ Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
+ "to the hostView");
+ continue;
+ }
+ if (!state.gone) {
float alpha = child.getAlpha();
float yTranslation = child.getTranslationY();
float zTranslation = child.getTranslationZ();
@@ -117,7 +136,7 @@
// apply visibility
int oldVisibility = child.getVisibility();
int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
- if (newVisibility != oldVisibility && !state.gone) {
+ if (newVisibility != oldVisibility) {
child.setVisibility(newVisibility);
}
@@ -135,13 +154,94 @@
if (height != newHeight) {
applyNewHeight(child, newHeight);
}
- } else {
- Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
- "to the hostView");
+
+ // apply clipping and shadow
+ float newNotificationEnd = newYTranslation + newHeight;
+ updateChildClippingAndShadow(child, newHeight,
+ newNotificationEnd - (previousNotificationEnd - mChildDividerHeight),
+ newHeight - (previousNotificationStart - newYTranslation));
+
+ previousNotificationStart = newYTranslation;
+ previousNotificationEnd = newNotificationEnd;
}
}
}
+ /**
+ * Updates the shadow outline and the clipping for a view.
+ *
+ * @param child the view to update
+ * @param realHeight the currently applied height of the view
+ * @param clipHeight the desired clip height, the rest of the view will be clipped from the top
+ * @param shadowHeight the desired height of the shadow, the shadow ends on the bottom
+ */
+ private void updateChildClippingAndShadow(View child, int realHeight, float clipHeight,
+ float shadowHeight) {
+ if (realHeight > shadowHeight) {
+ updateChildOutline(child, realHeight, shadowHeight);
+ } else {
+ updateChildOutline(child, realHeight, realHeight);
+ }
+ if (realHeight > clipHeight) {
+ updateChildClip(child, realHeight, clipHeight);
+ } else {
+ child.setClipBounds(null);
+ }
+ }
+
+ /**
+ * Updates the clipping of a view
+ *
+ * @param child the view to update
+ * @param height the currently applied height of the view
+ * @param clipHeight the desired clip height, the rest of the view will be clipped from the top
+ */
+ private void updateChildClip(View child, int height, float clipHeight) {
+ // The children currently have paddings inside themselfs because of the expansion
+ // visualization. In order for the clipping to work correctly we have to set the correct
+ // clip rect on the child.
+ View container = child.findViewById(R.id.container);
+ if (container != null) {
+ int clipInset = (int) (height - clipHeight);
+ mClipRect.set(0,
+ clipInset,
+ child.getWidth(),
+ height);
+ child.setClipBounds(mClipRect);
+ }
+ }
+
+ /**
+ * Updates the outline of a view
+ *
+ * @param child the view to update
+ * @param height the currently applied height of the view
+ * @param outlineHeight the desired height of the outline, the outline ends on the bottom
+ */
+ private void updateChildOutline(View child,
+ int height,
+ float outlineHeight) {
+ // The children currently have paddings inside themselfs because of the expansion
+ // visualization. In order for the shadows to work correctly we have to set the correct
+ // outline on the child.
+ View container = child.findViewById(R.id.container);
+ if (container != null) {
+ int shadowInset = (int) (height - outlineHeight);
+ getOutlineForSize(container.getLeft(),
+ container.getTop() + shadowInset,
+ container.getWidth(),
+ container.getHeight() - shadowInset,
+ mChildOutline);
+ child.setOutline(mChildOutline);
+ }
+ }
+
+ private void getOutlineForSize(int leftInset, int topInset, int width, int height,
+ Outline result) {
+ result.setRoundRect(leftInset, topInset, leftInset + width, topInset + height,
+ mBackgroundRoundedRectCornerRadius);
+ }
+
private void applyNewHeight(View child, int newHeight) {
ViewGroup.LayoutParams lp = child.getLayoutParams();
lp.height = newHeight;
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index 3c4e951..79f8a1f 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -27,6 +27,8 @@
LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor
+LOCAL_MULTILIB := 32
+
include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index c6972b1..fec9dda 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -51,6 +51,7 @@
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.util.ArraySet;
import android.util.Log;
import android.util.TypedValue;
import android.view.InputDevice;
@@ -83,6 +84,15 @@
private static final boolean SHOW_SILENT_TOGGLE = true;
+ /* Valid settings for global actions keys.
+ * see config.xml config_globalActionList */
+ private static final String GLOBAL_ACTION_KEY_POWER = "power";
+ private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
+ private static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
+ private static final String GLOBAL_ACTION_KEY_SILENT = "silent";
+ private static final String GLOBAL_ACTION_KEY_USERS = "users";
+ private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
+
private final Context mContext;
private final WindowManagerFuncs mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -235,92 +245,36 @@
onAirplaneModeChanged();
mItems = new ArrayList<Action>();
+ String[] defaultActions = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_globalActionsList);
- // first: power off
- mItems.add(
- new SinglePressAction(
- com.android.internal.R.drawable.ic_lock_power_off,
- R.string.global_action_power_off) {
-
- public void onPress() {
- // shutdown by making sure radio and power are handled accordingly.
- mWindowManagerFuncs.shutdown(true);
- }
-
- public boolean onLongPress() {
- mWindowManagerFuncs.rebootSafeMode(true);
- return true;
- }
-
- public boolean showDuringKeyguard() {
- return true;
- }
-
- public boolean showBeforeProvisioning() {
- return true;
- }
- });
-
- // next: airplane mode
- mItems.add(mAirplaneModeOn);
-
- // next: bug report, if enabled
- if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
- mItems.add(
- new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
- R.string.global_action_bug_report) {
-
- public void onPress() {
- AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
- builder.setTitle(com.android.internal.R.string.bugreport_title);
- builder.setMessage(com.android.internal.R.string.bugreport_message);
- builder.setNegativeButton(com.android.internal.R.string.cancel, null);
- builder.setPositiveButton(com.android.internal.R.string.report,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Add a little delay before executing, to give the
- // dialog a chance to go away before it takes a
- // screenshot.
- mHandler.postDelayed(new Runnable() {
- @Override public void run() {
- try {
- ActivityManagerNative.getDefault()
- .requestBugReport();
- } catch (RemoteException e) {
- }
- }
- }, 500);
- }
- });
- AlertDialog dialog = builder.create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
- dialog.show();
- }
-
- public boolean onLongPress() {
- return false;
- }
-
- public boolean showDuringKeyguard() {
- return true;
- }
-
- public boolean showBeforeProvisioning() {
- return false;
- }
- });
- }
-
- // last: silent mode
- if (mShowSilentToggle) {
- mItems.add(mSilentModeAction);
- }
-
- // one more thing: optionally add a list of users to switch to
- if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
- addUsersToMenu(mItems);
+ ArraySet<String> addedKeys = new ArraySet<String>();
+ for (int i = 0; i < defaultActions.length; i++) {
+ String actionKey = defaultActions[i];
+ if (addedKeys.contains(actionKey)) {
+ // If we already have added this, don't add it again.
+ continue;
+ }
+ if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
+ mItems.add(getPowerAction());
+ } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
+ mItems.add(mAirplaneModeOn);
+ } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)
+ && (Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner())) {
+ mItems.add(getBugReportAction());
+ } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey) && mShowSilentToggle) {
+ mItems.add(mSilentModeAction);
+ } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)
+ && SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+ addUsersToMenu(mItems);
+ } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
+ mItems.add(getSettingsAction());
+ } else {
+ Log.e(TAG, "Invalid global action key " + actionKey);
+ }
+ // Add here so we don't add more than one.
+ addedKeys.add(actionKey);
}
mAdapter = new MyAdapter();
@@ -350,6 +304,105 @@
return dialog;
}
+ private Action getPowerAction() {
+ return new SinglePressAction(
+ com.android.internal.R.drawable.ic_lock_power_off,
+ R.string.global_action_power_off) {
+
+ public void onPress() {
+ // shutdown by making sure radio and power are handled accordingly.
+ mWindowManagerFuncs.shutdown(true);
+ }
+
+ public boolean onLongPress() {
+ mWindowManagerFuncs.rebootSafeMode(true);
+ return true;
+ }
+
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ public boolean showBeforeProvisioning() {
+ return true;
+ }
+ };
+ }
+
+ private Action getBugReportAction() {
+ return new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+ R.string.global_action_bug_report) {
+
+ public void onPress() {
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+ builder.setTitle(com.android.internal.R.string.bugreport_title);
+ builder.setMessage(com.android.internal.R.string.bugreport_message);
+ builder.setNegativeButton(com.android.internal.R.string.cancel, null);
+ builder.setPositiveButton(com.android.internal.R.string.report,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // Add a little delay before executing, to give the
+ // dialog a chance to go away before it takes a
+ // screenshot.
+ mHandler.postDelayed(new Runnable() {
+ @Override public void run() {
+ try {
+ ActivityManagerNative.getDefault()
+ .requestBugReport();
+ } catch (RemoteException e) {
+ }
+ }
+ }, 500);
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ dialog.show();
+ }
+
+ public boolean onLongPress() {
+ return false;
+ }
+
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+ };
+ }
+
+ private Action getSettingsAction() {
+ return new SinglePressAction(com.android.internal.R.drawable.ic_settings,
+ R.string.global_action_settings) {
+
+ @Override
+ public void onPress() {
+ Intent intent = new Intent(Settings.ACTION_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ }
+
+ @Override
+ public boolean onLongPress() {
+ return false;
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+ };
+ }
+
private UserInfo getCurrentUser() {
try {
return ActivityManagerNative.getDefault().getCurrentUser();
diff --git a/preloaded-classes b/preloaded-classes
index 35c52ad..4413cd3 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -601,8 +601,6 @@
android.media.ResampleInputStream
android.media.SoundPool
android.media.ToneGenerator
-android.media.videoeditor.MediaArtistNativeHelper
-android.media.videoeditor.VideoEditorProfile
android.mtp.MtpDatabase
android.mtp.MtpDevice
android.mtp.MtpDeviceInfo
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index bce85ce..7249985 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -106,22 +106,33 @@
.append("Kernel: ")
.append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n"))
.append("\n").toString();
+ final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
String recovery = RecoverySystem.handleAftermath();
if (recovery != null && db != null) {
db.addText("SYSTEM_RECOVERY_LOG", headers + recovery);
}
+ String lastKmsgFooter = "";
+ if (bootReason != null) {
+ lastKmsgFooter = new StringBuilder(512)
+ .append("\n")
+ .append("Boot info:\n")
+ .append("Last boot reason: ").append(bootReason).append("\n")
+ .toString();
+ }
+
if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
String now = Long.toString(System.currentTimeMillis());
SystemProperties.set("ro.runtime.firstboot", now);
if (db != null) db.addText("SYSTEM_BOOT", headers);
// Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
- addFileToDropBox(db, prefs, headers, "/proc/last_kmsg",
- -LOG_SIZE, "SYSTEM_LAST_KMSG");
- addFileToDropBox(db, prefs, headers, "/sys/fs/pstore/console-ramoops",
- -LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter,
+ "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter,
+ "/sys/fs/pstore/console-ramoops", -LOG_SIZE,
+ "SYSTEM_LAST_KMSG");
addFileToDropBox(db, prefs, headers, "/cache/recovery/log",
-LOG_SIZE, "SYSTEM_RECOVERY_LOG");
addFileToDropBox(db, prefs, headers, "/data/dontpanic/apanic_console",
@@ -161,6 +172,14 @@
private static void addFileToDropBox(
DropBoxManager db, SharedPreferences prefs,
String headers, String filename, int maxSize, String tag) throws IOException {
+ addFileWithFootersToDropBox(db, prefs, headers, "", filename, maxSize,
+ tag);
+ }
+
+ private static void addFileWithFootersToDropBox(
+ DropBoxManager db, SharedPreferences prefs,
+ String headers, String footers, String filename, int maxSize,
+ String tag) throws IOException {
if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled
File file = new File(filename);
@@ -176,7 +195,7 @@
}
Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
- db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"));
+ db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") + footers);
}
private static void addAuditErrorsToDropBox(DropBoxManager db, SharedPreferences prefs,
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e6163bd..62deec2 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -450,6 +450,27 @@
if (provider == null) {
Slog.e(TAG, "no geofence provider found");
}
+
+ String[] testProviderStrings = resources.getStringArray(
+ com.android.internal.R.array.config_testLocationProviders);
+ for (String testProviderString : testProviderStrings) {
+ String fragments[] = testProviderString.split(",");
+ String name = fragments[0].trim();
+ if (mProvidersByName.get(name) != null) {
+ throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
+ }
+ ProviderProperties properties = new ProviderProperties(
+ Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
+ Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
+ Boolean.parseBoolean(fragments[3]) /* requiresCell */,
+ Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
+ Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
+ Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
+ Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
+ Integer.parseInt(fragments[8]) /* powerRequirement */,
+ Integer.parseInt(fragments[9]) /* accuracy */);
+ addTestProviderLocked(name, properties);
+ }
}
/**
@@ -2204,7 +2225,6 @@
long identity = Binder.clearCallingIdentity();
synchronized (mLock) {
- MockProvider provider = new MockProvider(name, this, properties);
// remove the real provider if we are replacing GPS or network provider
if (LocationManager.GPS_PROVIDER.equals(name)
|| LocationManager.NETWORK_PROVIDER.equals(name)
@@ -2214,18 +2234,23 @@
removeProviderLocked(p);
}
}
- if (mProvidersByName.get(name) != null) {
- throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
- }
- addProviderLocked(provider);
- mMockProviders.put(name, provider);
- mLastLocation.put(name, null);
- mLastLocationCoarseInterval.put(name, null);
+ addTestProviderLocked(name, properties);
updateProvidersLocked();
}
Binder.restoreCallingIdentity(identity);
}
+ private void addTestProviderLocked(String name, ProviderProperties properties) {
+ if (mProvidersByName.get(name) != null) {
+ throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
+ }
+ MockProvider provider = new MockProvider(name, this, properties);
+ addProviderLocked(provider);
+ mMockProviders.put(name, provider);
+ mLastLocation.put(name, null);
+ mLastLocationCoarseInterval.put(name, null);
+ }
+
@Override
public void removeTestProvider(String provider) {
checkMockPermissionsSafe();
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 9629bd1..705862a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -153,7 +153,7 @@
*/
private NativeDaemonConnector mConnector;
- private final Handler mMainHandler = new Handler();
+ private final Handler mFgHandler;
private IBatteryStats mBatteryStats;
@@ -203,6 +203,9 @@
private NetworkManagementService(Context context, String socket) {
mContext = context;
+ // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
+ mFgHandler = new Handler(FgThread.get().getLooper());
+
if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
return;
}
@@ -271,14 +274,17 @@
*/
private void notifyInterfaceStatusChanged(String iface, boolean up) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -287,14 +293,17 @@
*/
private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -302,14 +311,17 @@
*/
private void notifyInterfaceAdded(String iface) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceAdded(iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceAdded(iface);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -322,14 +334,17 @@
mActiveQuotas.remove(iface);
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceRemoved(iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceRemoved(iface);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -337,14 +352,17 @@
*/
private void notifyLimitReached(String limitName, String iface) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).limitReached(limitName, iface);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).limitReached(limitName, iface);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -357,15 +375,18 @@
}
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
- Integer.toString(type), active, tsNanos);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
+ Integer.toString(type), active, tsNanos);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
boolean report = false;
synchronized (mIdleTimerLock) {
@@ -456,14 +477,17 @@
*/
private void notifyAddressUpdated(String iface, LinkAddress address) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).addressUpdated(iface, address);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).addressUpdated(iface, address);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -471,14 +495,17 @@
*/
private void notifyAddressRemoved(String iface, LinkAddress address) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).addressRemoved(iface, address);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).addressRemoved(iface, address);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
/**
@@ -486,14 +513,18 @@
*/
private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
final int length = mObservers.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, addresses);
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime,
+ addresses);
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mObservers.finishBroadcast();
}
- mObservers.finishBroadcast();
}
//
@@ -509,7 +540,7 @@
mConnectedSignal.countDown();
mConnectedSignal = null;
} else {
- mMainHandler.post(new Runnable() {
+ mFgHandler.post(new Runnable() {
@Override
public void run() {
prepareNativeDaemon();
@@ -1270,7 +1301,7 @@
if (ConnectivityManager.isNetworkTypeMobile(type)) {
mNetworkActive = false;
}
- mMainHandler.post(new Runnable() {
+ mFgHandler.post(new Runnable() {
@Override public void run() {
notifyInterfaceClassActivity(type, true, SystemClock.elapsedRealtimeNanos());
}
@@ -1297,7 +1328,7 @@
throw e.rethrowAsParcelableException();
}
mActiveIdleTimers.remove(iface);
- mMainHandler.post(new Runnable() {
+ mFgHandler.post(new Runnable() {
@Override public void run() {
notifyInterfaceClassActivity(params.type, false,
SystemClock.elapsedRealtimeNanos());
@@ -1880,14 +1911,17 @@
private void reportNetworkActive() {
final int length = mNetworkActivityListeners.beginBroadcast();
- for (int i = 0; i < length; i++) {
- try {
- mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
- } catch (RemoteException e) {
- } catch (RuntimeException e) {
+ try {
+ for (int i = 0; i < length; i++) {
+ try {
+ mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
+ } catch (RemoteException e) {
+ } catch (RuntimeException e) {
+ }
}
+ } finally {
+ mNetworkActivityListeners.finishBroadcast();
}
- mNetworkActivityListeners.finishBroadcast();
}
/** {@inheritDoc} */
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
new file mode 100644
index 0000000..8a30e50
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014 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;
+
+import android.Manifest.permission;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.INetworkScoreService;
+import android.net.NetworkKey;
+import android.net.NetworkScorerAppManager;
+import android.net.RssiCurve;
+import android.net.ScoredNetwork;
+import android.text.TextUtils;
+
+import com.android.internal.R;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Backing service for {@link android.net.NetworkScoreManager}.
+ * @hide
+ */
+public class NetworkScoreService extends INetworkScoreService.Stub {
+ private static final String TAG = "NetworkScoreService";
+
+ /** SharedPreference bit set to true after the service is first initialized. */
+ private static final String PREF_SCORING_PROVISIONED = "is_provisioned";
+
+ private final Context mContext;
+
+ // TODO: Delete this temporary class once we have a real place for scores.
+ private final Map<NetworkKey, RssiCurve> mScoredNetworks;
+
+ public NetworkScoreService(Context context) {
+ mContext = context;
+ mScoredNetworks = new HashMap<>();
+ }
+
+ /** Called when the system is ready to run third-party code but before it actually does so. */
+ void systemReady() {
+ SharedPreferences prefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE);
+ if (!prefs.getBoolean(PREF_SCORING_PROVISIONED, false)) {
+ // On first run, we try to initialize the scorer to the one configured at build time.
+ // This will be a no-op if the scorer isn't actually valid.
+ String defaultPackage = mContext.getResources().getString(
+ R.string.config_defaultNetworkScorerPackageName);
+ if (!TextUtils.isEmpty(defaultPackage)) {
+ NetworkScorerAppManager.setActiveScorer(mContext, defaultPackage);
+ }
+ prefs.edit().putBoolean(PREF_SCORING_PROVISIONED, true).apply();
+ }
+ }
+
+ @Override
+ public boolean updateScores(ScoredNetwork[] networks) {
+ if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
+ throw new SecurityException("Caller with UID " + getCallingUid() +
+ " is not the active scorer.");
+ }
+
+ // TODO: Propagate these scores down to the network subsystem layer instead of just holding
+ // them in memory.
+ for (ScoredNetwork network : networks) {
+ mScoredNetworks.put(network.networkKey, network.rssiCurve);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean clearScores() {
+ // Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETWORKS) should
+ // be allowed to flush all scores.
+ if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) ||
+ mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) ==
+ PackageManager.PERMISSION_GRANTED) {
+ clearInternal();
+ return true;
+ } else {
+ throw new SecurityException(
+ "Caller is neither the active scorer nor the scorer manager.");
+ }
+ }
+
+ @Override
+ public boolean setActiveScorer(String packageName) {
+ mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+ // Preemptively clear scores even though the set operation could fail. We do this for safety
+ // as scores should never be compared across apps; in practice, Settings should only be
+ // allowing valid apps to be set as scorers, so failure here should be rare.
+ clearInternal();
+ return NetworkScorerAppManager.setActiveScorer(mContext, packageName);
+ }
+
+ /** Clear scores. Callers are responsible for checking permissions as appropriate. */
+ private void clearInternal() {
+ // TODO: Propagate the flush down to the network subsystem layer.
+ mScoredNetworks.clear();
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+ String currentScorer = NetworkScorerAppManager.getActiveScorer(mContext);
+ if (currentScorer == null) {
+ writer.println("Scoring is disabled.");
+ return;
+ }
+ writer.println("Current scorer: " + currentScorer);
+ if (mScoredNetworks.isEmpty()) {
+ writer.println("No networks scored.");
+ } else {
+ for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) {
+ writer.println(entry.getKey() + ": " + entry.getValue());
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7607419..8fa076b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,8 +17,10 @@
package com.android.server.am;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
import static com.android.internal.util.XmlUtils.readIntAttribute;
import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
@@ -724,6 +726,7 @@
private static final String ATTR_URI = "uri";
private static final String ATTR_MODE_FLAGS = "modeFlags";
private static final String ATTR_CREATED_TIME = "createdTime";
+ private static final String ATTR_PREFIX = "prefix";
/**
* Global set of specific {@link Uri} permissions that have been granted.
@@ -731,8 +734,41 @@
* to {@link UriPermission#uri} to {@link UriPermission}.
*/
@GuardedBy("this")
- private final SparseArray<ArrayMap<Uri, UriPermission>>
- mGrantedUriPermissions = new SparseArray<ArrayMap<Uri, UriPermission>>();
+ private final SparseArray<ArrayMap<GrantUri, UriPermission>>
+ mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
+
+ public static class GrantUri {
+ public final Uri uri;
+ public final boolean prefix;
+
+ public GrantUri(Uri uri, boolean prefix) {
+ this.uri = uri;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof GrantUri) {
+ GrantUri other = (GrantUri) o;
+ return uri.equals(other.uri) && prefix == other.prefix;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ if (prefix) {
+ return uri.toString() + " [prefix]";
+ } else {
+ return uri.toString();
+ }
+ }
+ }
CoreSettingsObserver mCoreSettingsObserver;
@@ -3417,11 +3453,14 @@
* @param token The Binder token referencing the Activity we want to finish.
* @param resultCode Result code, if any, from this Activity.
* @param resultData Result data (Intent), if any, from this Activity.
+ * @param finishTask Whether to finish the task associated with this Activity. Only applies to
+ * the root Activity in the task.
*
* @return Returns true if the activity successfully finished, or false if it is still running.
*/
@Override
- public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
+ public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
+ boolean finishTask) {
// Refuse possible leaked file descriptors
if (resultData != null && resultData.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -3432,6 +3471,9 @@
if (r == null) {
return true;
}
+ // Keep track of the root activity of the task before we finish it
+ TaskRecord tr = r.task;
+ ActivityRecord rootR = tr.getRootActivity();
if (mController != null) {
// Find the first activity that is not finishing.
ActivityRecord next = r.task.stack.topRunningActivityLocked(token, 0);
@@ -3451,10 +3493,21 @@
}
}
final long origId = Binder.clearCallingIdentity();
- boolean res = r.task.stack.requestFinishActivityLocked(token, resultCode,
- resultData, "app-request", true);
- Binder.restoreCallingIdentity(origId);
- return res;
+ try {
+ boolean res;
+ if (finishTask && r == rootR) {
+ // If requested, remove the task that is associated to this activity only if it
+ // was the root activity in the task. The result code and data is ignored because
+ // we don't support returning them across task boundaries.
+ res = removeTaskByIdLocked(tr.taskId, 0);
+ } else {
+ res = tr.stack.requestFinishActivityLocked(token, resultCode,
+ resultData, "app-request", true);
+ }
+ return res;
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
}
@@ -5822,7 +5875,7 @@
* in {@link ContentProvider}.
*/
private final boolean checkHoldingPermissionsLocked(
- IPackageManager pm, ProviderInfo pi, Uri uri, int uid, int modeFlags) {
+ IPackageManager pm, ProviderInfo pi, Uri uri, int uid, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
@@ -5918,18 +5971,17 @@
return pi;
}
- private UriPermission findUriPermissionLocked(int targetUid, Uri uri) {
- ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+ private UriPermission findUriPermissionLocked(int targetUid, GrantUri uri) {
+ final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris != null) {
return targetUris.get(uri);
- } else {
- return null;
}
+ return null;
}
- private UriPermission findOrCreateUriPermissionLocked(
- String sourcePkg, String targetPkg, int targetUid, Uri uri) {
- ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+ private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
+ String targetPkg, int targetUid, GrantUri uri) {
+ ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
if (targetUris == null) {
targetUris = Maps.newArrayMap();
mGrantedUriPermissions.put(targetUid, targetUris);
@@ -5944,21 +5996,40 @@
return perm;
}
- private final boolean checkUriPermissionLocked(
- Uri uri, int uid, int modeFlags, int minStrength) {
+ private final boolean checkUriPermissionLocked(Uri uri, int uid, final int modeFlags) {
+ final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+ final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
+ : UriPermission.STRENGTH_OWNED;
+
// Root gets to do everything.
if (uid == 0) {
return true;
}
- ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
if (perms == null) return false;
- UriPermission perm = perms.get(uri);
- if (perm == null) return false;
- return perm.getStrength(modeFlags) >= minStrength;
+
+ // First look for exact match
+ final UriPermission exactPerm = perms.get(new GrantUri(uri, false));
+ if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
+ return true;
+ }
+
+ // No exact match, look for prefixes
+ final int N = perms.size();
+ for (int i = 0; i < N; i++) {
+ final UriPermission perm = perms.valueAt(i);
+ if (perm.uri.prefix && uri.isPathPrefixMatch(perm.uri.uri)
+ && perm.getStrength(modeFlags) >= minStrength) {
+ return true;
+ }
+ }
+
+ return false;
}
@Override
- public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+ public int checkUriPermission(Uri uri, int pid, int uid, final int modeFlags) {
enforceNotIsolatedCaller("checkUriPermission");
// Another redirected-binder-call permissions check as in
@@ -5973,8 +6044,8 @@
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
- synchronized(this) {
- return checkUriPermissionLocked(uri, uid, modeFlags, UriPermission.STRENGTH_OWNED)
+ synchronized (this) {
+ return checkUriPermissionLocked(uri, uid, modeFlags)
? PackageManager.PERMISSION_GRANTED
: PackageManager.PERMISSION_DENIED;
}
@@ -5990,11 +6061,8 @@
* lastTargetUid else set that to -1.
*/
int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
- Uri uri, int modeFlags, int lastTargetUid) {
- final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ Uri uri, final int modeFlags, int lastTargetUid) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return -1;
}
@@ -6089,9 +6157,7 @@
if (callingUid != Process.myUid()) {
if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
// Require they hold a strong enough Uri permission
- final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
- : UriPermission.STRENGTH_OWNED;
- if (!checkUriPermissionLocked(uri, callingUid, modeFlags, minStrength)) {
+ if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
throw new SecurityException("Uid " + callingUid
+ " does not have permission to uri " + uri);
}
@@ -6103,19 +6169,16 @@
@Override
public int checkGrantUriPermission(int callingUid, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("checkGrantUriPermission");
synchronized(this) {
return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
}
}
- void grantUriPermissionUncheckedLocked(
- int targetUid, String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
- final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, Uri uri,
+ final int modeFlags, UriPermissionOwner owner) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return;
}
@@ -6133,13 +6196,14 @@
return;
}
+ final boolean prefix = (modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
final UriPermission perm = findOrCreateUriPermissionLocked(
- pi.packageName, targetPkg, targetUid, uri);
- perm.grantModes(modeFlags, persistable, owner);
+ pi.packageName, targetPkg, targetUid, new GrantUri(uri, prefix));
+ perm.grantModes(modeFlags, owner);
}
void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri,
- int modeFlags, UriPermissionOwner owner) {
+ final int modeFlags, UriPermissionOwner owner) {
if (targetPkg == null) {
throw new NullPointerException("targetPkg");
}
@@ -6253,7 +6317,7 @@
@Override
public void grantUriPermission(IApplicationThread caller, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("grantUriPermission");
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6269,32 +6333,32 @@
throw new IllegalArgumentException("null uri");
}
- // Persistable only supported through Intents
- Preconditions.checkFlagsArgument(modeFlags,
- Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
- grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
- null);
+ grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, null);
}
}
void removeUriPermissionIfNeededLocked(UriPermission perm) {
- if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
- |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.get(perm.targetUid);
+ if (perm.modeFlags == 0) {
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+ perm.targetUid);
if (perms != null) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Removing " + perm.targetUid + " permission to " + perm.uri);
+
perms.remove(perm.uri);
- if (perms.size() == 0) {
+ if (perms.isEmpty()) {
mGrantedUriPermissions.remove(perm.targetUid);
}
}
}
}
- private void revokeUriPermissionLocked(int callingUid, Uri uri, int modeFlags) {
+ private void revokeUriPermissionLocked(int callingUid, Uri uri, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + uri);
final IPackageManager pm = AppGlobals.getPackageManager();
@@ -6318,46 +6382,29 @@
boolean persistChanged = false;
// Go through all of the permissions and remove any that match.
- final List<String> SEGMENTS = uri.getPathSegments();
- if (SEGMENTS != null) {
- final int NS = SEGMENTS.size();
- int N = mGrantedUriPermissions.size();
- for (int i=0; i<N; i++) {
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.valueAt(i);
- Iterator<UriPermission> it = perms.values().iterator();
- toploop:
- while (it.hasNext()) {
- UriPermission perm = it.next();
- Uri targetUri = perm.uri;
- if (!authority.equals(targetUri.getAuthority())) {
- continue;
- }
- List<String> targetSegments = targetUri.getPathSegments();
- if (targetSegments == null) {
- continue;
- }
- if (targetSegments.size() < NS) {
- continue;
- }
- for (int j=0; j<NS; j++) {
- if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
- continue toploop;
- }
- }
- if (DEBUG_URI_PERMISSION) Slog.v(TAG,
- "Revoking " + perm.targetUid + " permission to " + perm.uri);
- persistChanged |= perm.clearModes(modeFlags, true);
+ int N = mGrantedUriPermissions.size();
+ for (int i = 0; i < N; i++) {
+ final int targetUid = mGrantedUriPermissions.keyAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
+ for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
+ final UriPermission perm = it.next();
+ if (perm.uri.uri.isPathPrefixMatch(uri)) {
+ if (DEBUG_URI_PERMISSION)
+ Slog.v(TAG,
+ "Revoking " + perm.targetUid + " permission to " + perm.uri);
+ persistChanged |= perm.revokeModes(
+ modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
if (perm.modeFlags == 0) {
it.remove();
}
}
- if (perms.size() == 0) {
- mGrantedUriPermissions.remove(
- mGrantedUriPermissions.keyAt(i));
- N--;
- i--;
- }
+ }
+
+ if (perms.isEmpty()) {
+ mGrantedUriPermissions.remove(targetUid);
+ N--;
+ i--;
}
}
@@ -6368,7 +6415,7 @@
@Override
public void revokeUriPermission(IApplicationThread caller, Uri uri,
- int modeFlags) {
+ final int modeFlags) {
enforceNotIsolatedCaller("revokeUriPermission");
synchronized(this) {
final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6382,9 +6429,7 @@
return;
}
- modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- if (modeFlags == 0) {
+ if (!Intent.isAccessUriMode(modeFlags)) {
return;
}
@@ -6419,20 +6464,22 @@
boolean persistChanged = false;
- final int size = mGrantedUriPermissions.size();
- for (int i = 0; i < size; i++) {
+ int N = mGrantedUriPermissions.size();
+ for (int i = 0; i < N; i++) {
+ final int targetUid = mGrantedUriPermissions.keyAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
// Only inspect grants matching user
if (userHandle == UserHandle.USER_ALL
- || userHandle == UserHandle.getUserId(mGrantedUriPermissions.keyAt(i))) {
- final Iterator<UriPermission> it = mGrantedUriPermissions.valueAt(i)
- .values().iterator();
- while (it.hasNext()) {
+ || userHandle == UserHandle.getUserId(targetUid)) {
+ for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
final UriPermission perm = it.next();
// Only inspect grants matching package
if (packageName == null || perm.sourcePkg.equals(packageName)
|| perm.targetPkg.equals(packageName)) {
- persistChanged |= perm.clearModes(~0, persistable);
+ persistChanged |= perm.revokeModes(
+ persistable ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
// Only remove when no modes remain; any persisted grants
// will keep this alive.
@@ -6441,6 +6488,12 @@
}
}
}
+
+ if (perms.isEmpty()) {
+ mGrantedUriPermissions.remove(targetUid);
+ N--;
+ i--;
+ }
}
}
@@ -6460,7 +6513,7 @@
@Override
public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
- Uri uri, int modeFlags) {
+ Uri uri, final int modeFlags) {
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -6514,8 +6567,9 @@
ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
synchronized (this) {
final int size = mGrantedUriPermissions.size();
- for (int i = 0 ; i < size; i++) {
- for (UriPermission perm : mGrantedUriPermissions.valueAt(i).values()) {
+ for (int i = 0; i < size; i++) {
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (perm.persistedModeFlags != 0) {
persist.add(perm.snapshot());
}
@@ -6536,7 +6590,8 @@
writeIntAttribute(out, ATTR_USER_HANDLE, perm.userHandle);
out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
- out.attribute(null, ATTR_URI, String.valueOf(perm.uri));
+ out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
+ writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
out.endTag(null, TAG_URI_GRANT);
@@ -6572,6 +6627,7 @@
final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
+ final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
@@ -6587,7 +6643,7 @@
}
if (targetUid != -1) {
final UriPermission perm = findOrCreateUriPermissionLocked(
- sourcePkg, targetPkg, targetUid, uri);
+ sourcePkg, targetPkg, targetUid, new GrantUri(uri, prefix));
perm.initPersistedModes(modeFlags, createdTime);
}
} else {
@@ -6609,7 +6665,7 @@
}
@Override
- public void takePersistableUriPermission(Uri uri, int modeFlags) {
+ public void takePersistableUriPermission(Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("takePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6617,13 +6673,28 @@
synchronized (this) {
final int callingUid = Binder.getCallingUid();
- final UriPermission perm = findUriPermissionLocked(callingUid, uri);
- if (perm == null) {
- throw new SecurityException("No permission grant found for UID " + callingUid
- + " and Uri " + uri.toSafeString());
+ boolean persistChanged = false;
+
+ UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+
+ final boolean exactValid = (exactPerm != null)
+ && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
+ final boolean prefixValid = (prefixPerm != null)
+ && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
+
+ if (!(exactValid || prefixValid)) {
+ throw new SecurityException("No persistable permission grants found for UID "
+ + callingUid + " and Uri " + uri.toSafeString());
}
- boolean persistChanged = perm.takePersistableModes(modeFlags);
+ if (exactValid) {
+ persistChanged |= exactPerm.takePersistableModes(modeFlags);
+ }
+ if (prefixValid) {
+ persistChanged |= prefixPerm.takePersistableModes(modeFlags);
+ }
+
persistChanged |= maybePrunePersistedUriGrantsLocked(callingUid);
if (persistChanged) {
@@ -6633,7 +6704,7 @@
}
@Override
- public void releasePersistableUriPermission(Uri uri, int modeFlags) {
+ public void releasePersistableUriPermission(Uri uri, final int modeFlags) {
enforceNotIsolatedCaller("releasePersistableUriPermission");
Preconditions.checkFlagsArgument(modeFlags,
@@ -6641,16 +6712,24 @@
synchronized (this) {
final int callingUid = Binder.getCallingUid();
+ boolean persistChanged = false;
- final UriPermission perm = findUriPermissionLocked(callingUid, uri);
- if (perm == null) {
- Slog.w(TAG, "No permission grant found for UID " + callingUid + " and Uri "
- + uri.toSafeString());
- return;
+ UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+ UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+ if (exactPerm == null && prefixPerm == null) {
+ throw new SecurityException("No permission grants found for UID " + callingUid
+ + " and Uri " + uri.toSafeString());
}
- final boolean persistChanged = perm.releasePersistableModes(modeFlags);
- removeUriPermissionIfNeededLocked(perm);
+ if (exactPerm != null) {
+ persistChanged |= exactPerm.releasePersistableModes(modeFlags);
+ removeUriPermissionIfNeededLocked(exactPerm);
+ }
+ if (prefixPerm != null) {
+ persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
+ removeUriPermissionIfNeededLocked(prefixPerm);
+ }
+
if (persistChanged) {
schedulePersistUriGrants();
}
@@ -6664,7 +6743,7 @@
* @return if any mutations occured that require persisting.
*/
private boolean maybePrunePersistedUriGrantsLocked(int uid) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
if (perms == null) return false;
if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
@@ -6714,13 +6793,12 @@
final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
synchronized (this) {
if (incoming) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+ callingUid);
if (perms == null) {
Slog.w(TAG, "No permission grants found for " + packageName);
} else {
- final int size = perms.size();
- for (int i = 0; i < size; i++) {
- final UriPermission perm = perms.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
result.add(perm.buildPersistedPublicApiObject());
}
@@ -6729,10 +6807,9 @@
} else {
final int size = mGrantedUriPermissions.size();
for (int i = 0; i < size; i++) {
- final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
- final int permsSize = perms.size();
- for (int j = 0; j < permsSize; j++) {
- final UriPermission perm = perms.valueAt(j);
+ final ArrayMap<GrantUri, UriPermission> perms =
+ mGrantedUriPermissions.valueAt(i);
+ for (UriPermission perm : perms.values()) {
if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
result.add(perm.buildPersistedPublicApiObject());
}
@@ -7084,6 +7161,24 @@
}
}
+ /**
+ * Removes the task with the specified task id.
+ *
+ * @param taskId Identifier of the task to be removed.
+ * @param flags Additional operational flags. May be 0 or
+ * {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}.
+ * @return Returns true if the given task was found and removed.
+ */
+ private boolean removeTaskByIdLocked(int taskId, int flags) {
+ TaskRecord tr = recentTaskForIdLocked(taskId);
+ if (tr != null) {
+ tr.removeTaskActivitiesLocked(-1, false);
+ cleanUpRemovedTaskLocked(tr, flags);
+ return true;
+ }
+ return false;
+ }
+
@Override
public boolean removeTask(int taskId, int flags) {
synchronized (this) {
@@ -7091,29 +7186,11 @@
"removeTask()");
long ident = Binder.clearCallingIdentity();
try {
- TaskRecord tr = recentTaskForIdLocked(taskId);
- if (tr != null) {
- ActivityRecord r = tr.removeTaskActivitiesLocked(-1, false);
- if (r != null) {
- cleanUpRemovedTaskLocked(tr, flags);
- return true;
- }
- if (tr.mActivities.size() == 0) {
- // Caller is just removing a recent task that is
- // not actively running. That is easy!
- cleanUpRemovedTaskLocked(tr, flags);
- return true;
- }
- Slog.w(TAG, "removeTask: task " + taskId
- + " does not have activities to remove, "
- + " but numActivities=" + tr.numActivities
- + ": " + tr);
- }
+ return removeTaskByIdLocked(taskId, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- return false;
}
/**
@@ -7240,6 +7317,9 @@
if (r == null) {
return null;
}
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
return mStackSupervisor.createActivityContainer(r, callback);
}
}
@@ -7599,11 +7679,11 @@
}
}
}
-
- ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
if (perms != null) {
- for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
- if (uri.getKey().getAuthority().equals(cpi.authority)) {
+ for (GrantUri uri : perms.keySet()) {
+ if (uri.uri.getAuthority().equals(cpi.authority)) {
return null;
}
}
@@ -11570,8 +11650,7 @@
if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
continue;
}
- ArrayMap<Uri, UriPermission> perms
- = mGrantedUriPermissions.valueAt(i);
+ final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
if (!printed) {
if (needSep) pw.println();
needSep = true;
@@ -11579,8 +11658,7 @@
printed = true;
printedAnything = true;
}
- pw.print(" * UID "); pw.print(uid);
- pw.println(" holds:");
+ pw.print(" * UID "); pw.print(uid); pw.println(" holds:");
for (UriPermission perm : perms.values()) {
pw.print(" "); pw.println(perm);
if (dumpAll) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d596472..3e59def 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -139,7 +139,7 @@
boolean forceNewConfig; // force re-create with new config next time
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last lauch of this activity
- ArrayList<ActivityStack> mChildContainers = new ArrayList<ActivityStack>();
+ ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
String stringName; // for caching of toString().
@@ -215,14 +215,7 @@
pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
}
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);
- }
+ uriPermissions.dump(pw, prefix);
}
pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
pw.print(" launchCount="); pw.print(launchCount);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 8dd4317..0acde09 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -36,6 +36,8 @@
import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.CONTAINER_STATE_HAS_SURFACE;
+
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -1066,9 +1068,9 @@
private void setVisibile(ActivityRecord r, boolean visible) {
r.visible = visible;
mWindowManager.setAppVisibility(r.appToken, visible);
- final ArrayList<ActivityStack> containers = r.mChildContainers;
+ final ArrayList<ActivityContainer> containers = r.mChildContainers;
for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
- ActivityContainer container = containers.get(containerNdx).mActivityContainer;
+ ActivityContainer container = containers.get(containerNdx);
container.setVisible(visible);
}
}
@@ -1270,6 +1272,7 @@
* occurred and the activity will be notified immediately.
*/
void notifyActivityDrawnLocked(ActivityRecord r) {
+ mActivityContainer.setDrawn();
if ((r == null)
|| (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
@@ -1336,7 +1339,8 @@
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
ActivityRecord parent = mActivityContainer.mParentActivity;
- if (parent != null && parent.state != ActivityState.RESUMED) {
+ if ((parent != null && parent.state != ActivityState.RESUMED) ||
+ !mActivityContainer.isAttached()) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
@@ -2624,6 +2628,20 @@
return r;
}
+ void finishAllActivitiesLocked() {
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (r.finishing) {
+ continue;
+ }
+ Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r);
+ finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
+ }
+ }
+ }
+
final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
Intent resultData) {
final ActivityRecord srec = ActivityRecord.forToken(token);
@@ -2862,7 +2880,6 @@
}
if (activityRemoved) {
mStackSupervisor.resumeTopActivitiesLocked();
-
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 63f9d09..afef4ff 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -96,7 +96,6 @@
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -225,11 +224,11 @@
// TODO: Add listener for removal of references.
/** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
- SparseArray<WeakReference<ActivityContainer>> mActivityContainers =
- new SparseArray<WeakReference<ActivityContainer>>();
+ SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>();
/** Mapping from displayId to display current state */
- private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
+ private final SparseArray<ActivityDisplay> mActivityDisplays =
+ new SparseArray<ActivityDisplay>();
InputManagerInternal mInputManagerInternal;
@@ -265,7 +264,7 @@
mActivityDisplays.put(displayId, activityDisplay);
}
- createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
+ createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
@@ -1386,7 +1385,7 @@
}
// Need to create an app stack for this user.
- int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY);
+ int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
" stackId=" + stackId);
mFocusedStack = getStack(stackId);
@@ -2154,14 +2153,9 @@
}
ActivityStack getStack(int stackId) {
- WeakReference<ActivityContainer> weakReference = mActivityContainers.get(stackId);
- if (weakReference != null) {
- ActivityContainer activityContainer = weakReference.get();
- if (activityContainer != null) {
- return activityContainer.mStack;
- } else {
- mActivityContainers.remove(stackId);
- }
+ ActivityContainer activityContainer = mActivityContainers.get(stackId);
+ if (activityContainer != null) {
+ return activityContainer.mStack;
}
return null;
}
@@ -2191,49 +2185,26 @@
return null;
}
- ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId,
+ ActivityContainer createActivityContainer(ActivityRecord parentActivity,
IActivityContainerCallback callback) {
- ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId,
- callback);
- mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer));
- if (parentActivity != null) {
- parentActivity.mChildContainers.add(activityContainer.mStack);
- }
+ ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback);
+ mActivityContainers.put(activityContainer.mStackId, activityContainer);
+ parentActivity.mChildContainers.add(activityContainer);
return activityContainer;
}
- ActivityContainer createActivityContainer(ActivityRecord parentActivity,
- IActivityContainerCallback callback) {
- return createActivityContainer(parentActivity, getNextStackId(), callback);
- }
-
void removeChildActivityContainers(ActivityRecord parentActivity) {
- for (int ndx = mActivityContainers.size() - 1; ndx >= 0; --ndx) {
- final ActivityContainer container = mActivityContainers.valueAt(ndx).get();
- if (container == null) {
- mActivityContainers.removeAt(ndx);
- continue;
- }
- if (container.mParentActivity != parentActivity) {
- continue;
- }
-
- ActivityStack stack = container.mStack;
- ActivityRecord top = stack.topRunningNonDelayedActivityLocked(null);
- if (top != null) {
- // TODO: Make sure the next activity doesn't start up when top is destroyed.
- stack.destroyActivityLocked(top, true, true, "stack parent destroyed");
- }
- mActivityContainers.removeAt(ndx);
- container.detachLocked();
+ final ArrayList<ActivityContainer> childStacks = parentActivity.mChildContainers;
+ for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) {
+ ActivityContainer container = childStacks.remove(containerNdx);
+ container.release();
}
}
void deleteActivityContainer(IActivityContainer container) {
ActivityContainer activityContainer = (ActivityContainer)container;
if (activityContainer != null) {
- activityContainer.mStack.destroyActivitiesLocked(null, true,
- "deleteActivityContainer");
+ activityContainer.mStack.finishAllActivitiesLocked();
final ActivityRecord parent = activityContainer.mParentActivity;
if (parent != null) {
parent.mChildContainers.remove(activityContainer);
@@ -2244,14 +2215,14 @@
}
}
- private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
+ private int createStackOnDisplay(int stackId, int displayId) {
ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
if (activityDisplay == null) {
return -1;
}
- ActivityContainer activityContainer =
- createActivityContainer(parentActivity, stackId, null);
+ ActivityContainer activityContainer = new ActivityContainer(stackId);
+ mActivityContainers.put(stackId, activityContainer);
activityContainer.attachToDisplayLocked(activityDisplay);
return stackId;
}
@@ -2334,9 +2305,9 @@
}
boolean shutdownLocked(int timeout) {
- boolean timedout = false;
goingToSleepLocked();
+ boolean timedout = false;
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
boolean cantShutdown = false;
@@ -3028,26 +2999,28 @@
}
}
- class ActivityContainer extends IActivityContainer.Stub {
+ class ActivityContainer extends android.app.IActivityContainer.Stub {
final int mStackId;
- final IActivityContainerCallback mCallback;
+ IActivityContainerCallback mCallback = null;
final ActivityStack mStack;
- final ActivityRecord mParentActivity;
- final String mIdString;
+ ActivityRecord mParentActivity = null;
+ String mIdString;
boolean mVisible = true;
/** Display this ActivityStack is currently on. Null if not attached to a Display. */
ActivityDisplay mActivityDisplay;
- ActivityContainer(ActivityRecord parentActivity, int stackId,
- IActivityContainerCallback callback) {
+ final static int CONTAINER_STATE_HAS_SURFACE = 0;
+ final static int CONTAINER_STATE_NO_SURFACE = 1;
+ final static int CONTAINER_STATE_FINISHING = 2;
+ int mContainerState = CONTAINER_STATE_HAS_SURFACE;
+
+ ActivityContainer(int stackId) {
synchronized (mService) {
mStackId = stackId;
mStack = new ActivityStack(this);
- mParentActivity = parentActivity;
- mCallback = callback;
- mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+ mIdString = "ActivtyContainer{" + mStackId + "}";
if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
}
}
@@ -3097,6 +3070,14 @@
}
}
+ @Override
+ public void release() {
+ mContainerState = CONTAINER_STATE_FINISHING;
+ mStack.finishAllActivitiesLocked();
+ detachLocked();
+ mWindowManager.removeStack(mStackId);
+ }
+
private void detachLocked() {
if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
+ mActivityDisplay + " Callers=" + Debug.getCallers(2));
@@ -3110,13 +3091,6 @@
}
@Override
- public void detachFromDisplay() {
- synchronized (mService) {
- detachLocked();
- }
- }
-
- @Override
public final int startActivity(Intent intent) {
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
int userId = mService.handleIncomingUser(Binder.getCallingPid(),
@@ -3149,23 +3123,8 @@
}
@Override
- public void attachToSurface(Surface surface, int width, int height, int density) {
+ public void setSurface(Surface surface, int width, int height, int density) {
mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface");
-
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mService) {
- ActivityDisplay activityDisplay =
- new ActivityDisplay(surface, width, height, density);
- mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay);
- attachToDisplayLocked(activityDisplay);
- mStack.resumeTopActivityLocked(null);
- }
- if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display="
- + mActivityDisplay);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
}
ActivityStackSupervisor getOuter() {
@@ -3184,6 +3143,7 @@
}
}
+ // TODO: Make sure every change to ActivityRecord.visible results in a call to this.
void setVisible(boolean visible) {
if (mVisible != visible) {
mVisible = visible;
@@ -3194,52 +3154,114 @@
}
}
+ void setDrawn() {
+ }
+
@Override
public String toString() {
return mIdString + (mActivityDisplay == null ? "N" : "A");
}
}
+ private class VirtualActivityContainer extends ActivityContainer {
+ Surface mSurface;
+ boolean mDrawn = false;
+
+ VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
+ super(getNextStackId());
+ mParentActivity = parent;
+ mCallback = callback;
+ mContainerState = CONTAINER_STATE_NO_SURFACE;
+ mIdString = "VirtualActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+ }
+
+ @Override
+ public void setSurface(Surface surface, int width, int height, int density) {
+ super.setSurface(surface, width, height, density);
+
+ synchronized (mService) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ setSurfaceLocked(surface, width, height, density);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ private void setSurfaceLocked(Surface surface, int width, int height, int density) {
+ if (mContainerState == CONTAINER_STATE_FINISHING) {
+ return;
+ }
+ VirtualActivityDisplay virtualActivityDisplay =
+ (VirtualActivityDisplay) mActivityDisplay;
+ if (virtualActivityDisplay == null) {
+ virtualActivityDisplay =
+ new VirtualActivityDisplay(width, height, density);
+ mActivityDisplay = virtualActivityDisplay;
+ mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
+ attachToDisplayLocked(virtualActivityDisplay);
+ }
+
+ if (mSurface != null) {
+ mSurface.release();
+ }
+
+ mSurface = surface;
+ if (surface != null) {
+ mStack.resumeTopActivityLocked(null);
+ } else {
+ mContainerState = CONTAINER_STATE_NO_SURFACE;
+ ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
+// if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
+// mStack.startPausingLocked(false, true);
+// }
+ }
+
+ setSurfaceIfReady();
+
+ if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display="
+ + virtualActivityDisplay);
+ }
+
+ @Override
+ void setDrawn() {
+ synchronized (mService) {
+ mDrawn = true;
+ setSurfaceIfReady();
+ }
+ }
+
+ private void setSurfaceIfReady() {
+ if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReady: mDrawn=" + mDrawn +
+ " mContainerState=" + mContainerState + " mSurface=" + mSurface);
+ if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
+ ((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
+ mContainerState = CONTAINER_STATE_HAS_SURFACE;
+ }
+ }
+ }
+
/** Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s */
- final class ActivityDisplay {
+ class ActivityDisplay {
/** Actual Display this object tracks. */
int mDisplayId;
Display mDisplay;
DisplayInfo mDisplayInfo = new DisplayInfo();
- Surface mSurface;
/** All of the stacks on this display. Order matters, topmost stack is in front of all other
* stacks, bottommost behind. Accessed directly by ActivityManager package classes */
final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
- /** If this display is for an ActivityView then the VirtualDisplay created for it is stored
- * here. */
- VirtualDisplay mVirtualDisplay;
+ ActivityDisplay() {
+ }
ActivityDisplay(int displayId) {
init(mDisplayManager.getDisplay(displayId));
}
- ActivityDisplay(Surface surface, int width, int height, int density) {
- DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
- long ident = Binder.clearCallingIdentity();
- try {
- mVirtualDisplay = dm.createVirtualDisplay(mService.mContext,
- VIRTUAL_DISPLAY_BASE_NAME, width, height, density, surface,
- DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
- DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- init(mVirtualDisplay.getDisplay());
- mSurface = surface;
-
- mWindowManager.handleDisplayAdded(mDisplayId);
- }
-
- private void init(Display display) {
+ void init(Display display) {
mDisplay = display;
mDisplayId = display.getDisplayId();
mDisplay.getDisplayInfo(mDisplayInfo);
@@ -3255,11 +3277,6 @@
if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
- if (mStacks.isEmpty() && mVirtualDisplay != null) {
- mVirtualDisplay.release();
- mVirtualDisplay = null;
- }
- mSurface.release();
}
void getBounds(Point bounds) {
@@ -3270,8 +3287,42 @@
@Override
public String toString() {
- return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V")
- + " numStacks=" + mStacks.size() + "}";
+ return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
+ }
+ }
+
+ class VirtualActivityDisplay extends ActivityDisplay {
+ VirtualDisplay mVirtualDisplay;
+
+ VirtualActivityDisplay(int width, int height, int density) {
+ DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+ mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, VIRTUAL_DISPLAY_BASE_NAME,
+ width, height, density, null, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
+
+ init(mVirtualDisplay.getDisplay());
+
+ mWindowManager.handleDisplayAdded(mDisplayId);
+ }
+
+ void setSurface(Surface surface) {
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.setSurface(surface);
+ }
+ }
+
+ @Override
+ void detachActivitiesLocked(ActivityStack stack) {
+ super.detachActivitiesLocked(stack);
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.release();
+ mVirtualDisplay = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "VirtualActivityDisplay={" + mDisplayId + "}";
}
}
}
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index b12843b..443218c 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -29,6 +29,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
import java.net.InetSocketAddress;
import java.net.InetUnixAddress;
@@ -178,7 +179,7 @@
}
static int readExactly(FileDescriptor fd, byte[] buffer, int offset, int numBytes)
- throws ErrnoException {
+ throws ErrnoException, InterruptedIOException {
int totalRead = 0;
while (numBytes > 0) {
int n = Libcore.os.read(fd, buffer, offset + totalRead, numBytes);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 363a9b7..e54c95e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -193,14 +193,7 @@
pw.println(si.neededGrants);
}
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);
- }
+ si.uriPermissions.dump(pw, prefix);
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3a43521..80a219dd 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -139,6 +139,18 @@
}
}
+ /** Returns the first non-finishing activity from the root. */
+ ActivityRecord getRootActivity() {
+ for (int i = 0; i < mActivities.size(); i++) {
+ final ActivityRecord r = mActivities.get(i);
+ if (r.finishing) {
+ continue;
+ }
+ return r;
+ }
+ return null;
+ }
+
ActivityRecord getTopActivity() {
for (int i = mActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = mActivities.get(i);
@@ -305,7 +317,7 @@
}
public ActivityManager.TaskThumbnails getTaskThumbnailsLocked() {
- TaskAccessInfo info = getTaskAccessInfoLocked(true);
+ TaskAccessInfo info = getTaskAccessInfoLocked();
final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity != null && resumedActivity.thumbHolder == this) {
info.mainThumbnail = stack.screenshotActivities(resumedActivity);
@@ -325,7 +337,7 @@
}
// Return the information about the task, to figure out the top
// thumbnail to return.
- TaskAccessInfo info = getTaskAccessInfoLocked(true);
+ TaskAccessInfo info = getTaskAccessInfoLocked();
if (info.numSubThumbbails <= 0) {
return info.mainThumbnail != null ? info.mainThumbnail : lastThumbnail;
}
@@ -334,7 +346,7 @@
public ActivityRecord removeTaskActivitiesLocked(int subTaskIndex,
boolean taskRequired) {
- TaskAccessInfo info = getTaskAccessInfoLocked(false);
+ TaskAccessInfo info = getTaskAccessInfoLocked();
if (info.root == null) {
if (taskRequired) {
Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
@@ -369,7 +381,7 @@
return mTaskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE;
}
- public TaskAccessInfo getTaskAccessInfoLocked(boolean inclThumbs) {
+ public TaskAccessInfo getTaskAccessInfoLocked() {
final TaskAccessInfo thumbs = new TaskAccessInfo();
// How many different sub-thumbnails?
final int NA = mActivities.size();
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 1f12b74..4970b8d 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -17,15 +17,16 @@
package com.android.server.am;
import android.content.Intent;
-import android.net.Uri;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
+import com.android.server.am.ActivityManagerService.GrantUri;
import com.google.android.collect.Sets;
import java.io.PrintWriter;
import java.util.Comparator;
-import java.util.HashSet;
/**
* Description of a permission granted to an app to access a particular URI.
@@ -50,7 +51,7 @@
/** Cached UID of {@link #targetPkg}; should not be persisted */
final int targetUid;
- final Uri uri;
+ final GrantUri uri;
/**
* Allowed modes. All permission enforcement should use this field. Must
@@ -61,12 +62,13 @@
*/
int modeFlags = 0;
- /** Allowed modes with explicit owner. */
+ /** Allowed modes with active owner. */
int ownedModeFlags = 0;
/** Allowed modes without explicit owner. */
int globalModeFlags = 0;
/** Allowed modes that have been offered for possible persisting. */
int persistableModeFlags = 0;
+
/** Allowed modes that should be persisted across device boots. */
int persistedModeFlags = 0;
@@ -78,12 +80,12 @@
private static final long INVALID_TIME = Long.MIN_VALUE;
- private HashSet<UriPermissionOwner> mReadOwners;
- private HashSet<UriPermissionOwner> mWriteOwners;
+ private ArraySet<UriPermissionOwner> mReadOwners;
+ private ArraySet<UriPermissionOwner> mWriteOwners;
private String stringName;
- UriPermission(String sourcePkg, String targetPkg, int targetUid, Uri uri) {
+ UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
this.userHandle = UserHandle.getUserId(targetUid);
this.sourcePkg = sourcePkg;
this.targetPkg = targetPkg;
@@ -100,6 +102,9 @@
* global or owner grants.
*/
void initPersistedModes(int modeFlags, long createdTime) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
persistableModeFlags = modeFlags;
persistedModeFlags = modeFlags;
persistedCreateTime = createdTime;
@@ -107,7 +112,11 @@
updateModeFlags();
}
- void grantModes(int modeFlags, boolean persistable, UriPermissionOwner owner) {
+ void grantModes(int modeFlags, UriPermissionOwner owner) {
+ final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
if (persistable) {
persistableModeFlags |= modeFlags;
}
@@ -130,10 +139,14 @@
* @return if mode changes should trigger persisting.
*/
boolean takePersistableModes(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
if ((modeFlags & persistableModeFlags) != modeFlags) {
- throw new SecurityException("Requested flags 0x"
+ Slog.w(TAG, "Requested flags 0x"
+ Integer.toHexString(modeFlags) + ", but only 0x"
+ Integer.toHexString(persistableModeFlags) + " are allowed");
+ return false;
}
final int before = persistedModeFlags;
@@ -148,6 +161,9 @@
}
boolean releasePersistableModes(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
final int before = persistedModeFlags;
persistableModeFlags &= ~modeFlags;
@@ -164,7 +180,11 @@
/**
* @return if mode changes should trigger persisting.
*/
- boolean clearModes(int modeFlags, boolean persistable) {
+ boolean revokeModes(int modeFlags) {
+ final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
final int before = persistedModeFlags;
if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
@@ -208,6 +228,8 @@
* Return strength of this permission grant for the given flags.
*/
public int getStrength(int modeFlags) {
+ modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if ((persistableModeFlags & modeFlags) == modeFlags) {
return STRENGTH_PERSISTABLE;
} else if ((globalModeFlags & modeFlags) == modeFlags) {
@@ -221,7 +243,7 @@
private void addReadOwner(UriPermissionOwner owner) {
if (mReadOwners == null) {
- mReadOwners = Sets.newHashSet();
+ mReadOwners = Sets.newArraySet();
ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
updateModeFlags();
}
@@ -246,7 +268,7 @@
private void addWriteOwner(UriPermissionOwner owner) {
if (mWriteOwners == null) {
- mWriteOwners = Sets.newHashSet();
+ mWriteOwners = Sets.newArraySet();
ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
updateModeFlags();
}
@@ -333,7 +355,7 @@
final int userHandle;
final String sourcePkg;
final String targetPkg;
- final Uri uri;
+ final GrantUri uri;
final int persistedModeFlags;
final long persistedCreateTime;
@@ -352,6 +374,6 @@
}
public android.content.UriPermission buildPersistedPublicApiObject() {
- return new android.content.UriPermission(uri, persistedModeFlags, persistedCreateTime);
+ return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
}
}
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
index 7bbd3bc..65d7047 100644
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/am/UriPermissionOwner.java
@@ -20,8 +20,11 @@
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
+import android.util.ArraySet;
-import java.util.HashSet;
+import com.google.android.collect.Sets;
+
+import java.io.PrintWriter;
import java.util.Iterator;
final class UriPermissionOwner {
@@ -30,8 +33,8 @@
Binder externalToken;
- HashSet<UriPermission> readUriPermissions; // special access to reading uris.
- HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+ private ArraySet<UriPermission> mReadPerms;
+ private ArraySet<UriPermission> mWritePerms;
class ExternalToken extends Binder {
UriPermissionOwner getOwner() {
@@ -39,9 +42,9 @@
}
}
- UriPermissionOwner(ActivityManagerService _service, Object _owner) {
- service = _service;
- owner = _owner;
+ UriPermissionOwner(ActivityManagerService service, Object owner) {
+ this.service = service;
+ this.owner = owner;
}
Binder getExternalTokenLocked() {
@@ -64,82 +67,76 @@
}
void removeUriPermissionsLocked(int mode) {
- if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
- && readUriPermissions != null) {
- for (UriPermission perm : readUriPermissions) {
- perm.removeReadOwner(this);
- service.removeUriPermissionIfNeededLocked(perm);
- }
- readUriPermissions = null;
- }
- if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
- && writeUriPermissions != null) {
- for (UriPermission perm : writeUriPermissions) {
- perm.removeWriteOwner(this);
- service.removeUriPermissionIfNeededLocked(perm);
- }
- writeUriPermissions = null;
- }
+ removeUriPermissionLocked(null, mode);
}
void removeUriPermissionLocked(Uri uri, int mode) {
- if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
- && readUriPermissions != null) {
- Iterator<UriPermission> it = readUriPermissions.iterator();
+ if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+ && mReadPerms != null) {
+ Iterator<UriPermission> it = mReadPerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri.equals(perm.uri)) {
+ if (uri == null || uri.equals(perm.uri)) {
perm.removeReadOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
}
}
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
+ if (mReadPerms.isEmpty()) {
+ mReadPerms = null;
}
}
- if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
- && writeUriPermissions != null) {
- Iterator<UriPermission> it = writeUriPermissions.iterator();
+ if ((mode & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+ && mWritePerms != null) {
+ Iterator<UriPermission> it = mWritePerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (uri.equals(perm.uri)) {
+ if (uri == null || uri.equals(perm.uri)) {
perm.removeWriteOwner(this);
service.removeUriPermissionIfNeededLocked(perm);
it.remove();
}
}
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ if (mWritePerms.isEmpty()) {
+ mWritePerms = null;
}
}
}
public void addReadPermission(UriPermission perm) {
- if (readUriPermissions == null) {
- readUriPermissions = new HashSet<UriPermission>();
+ if (mReadPerms == null) {
+ mReadPerms = Sets.newArraySet();
}
- readUriPermissions.add(perm);
+ mReadPerms.add(perm);
}
public void addWritePermission(UriPermission perm) {
- if (writeUriPermissions == null) {
- writeUriPermissions = new HashSet<UriPermission>();
+ if (mWritePerms == null) {
+ mWritePerms = Sets.newArraySet();
}
- writeUriPermissions.add(perm);
+ mWritePerms.add(perm);
}
public void removeReadPermission(UriPermission perm) {
- readUriPermissions.remove(perm);
- if (readUriPermissions.size() == 0) {
- readUriPermissions = null;
+ mReadPerms.remove(perm);
+ if (mReadPerms.isEmpty()) {
+ mReadPerms = null;
}
}
public void removeWritePermission(UriPermission perm) {
- writeUriPermissions.remove(perm);
- if (writeUriPermissions.size() == 0) {
- writeUriPermissions = null;
+ mWritePerms.remove(perm);
+ if (mWritePerms.isEmpty()) {
+ mWritePerms = null;
+ }
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ if (mReadPerms != null) {
+ pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
+ }
+ if (mWritePerms != null) {
+ pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
}
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 2c8f1b4..91afec7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -95,6 +95,14 @@
}
}
+ static boolean shouldBlank(int state) {
+ return state == Display.STATE_OFF;
+ }
+
+ static boolean shouldUnblank(int state) {
+ return state == Display.STATE_ON || state == Display.STATE_DOZING;
+ }
+
private final class LocalDisplayDevice extends DisplayDevice {
private final int mBuiltInDisplayId;
private final SurfaceControl.PhysicalDisplayInfo mPhys;
@@ -180,9 +188,9 @@
@Override
public void requestDisplayStateLocked(int state) {
if (mState != state) {
- if (state == Display.STATE_OFF && mState != Display.STATE_OFF) {
+ if (shouldBlank(state) && !shouldBlank(mState)) {
SurfaceControl.blankDisplay(getDisplayTokenLocked());
- } else if (state != Display.STATE_OFF && mState == Display.STATE_OFF) {
+ } else if (shouldUnblank(state) && !shouldUnblank(mState)) {
SurfaceControl.unblankDisplay(getDisplayTokenLocked());
}
mState = state;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5b597a3..c8bdb4c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -52,6 +52,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
+import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -64,6 +65,7 @@
import android.service.notification.INotificationListener;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -78,6 +80,7 @@
import com.android.internal.R;
import com.android.internal.notification.NotificationScorer;
+import com.android.internal.util.FastXmlSerializer;
import com.android.server.EventLogTags;
import com.android.server.notification.NotificationUsageStats.SingleNotificationStats;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -87,11 +90,13 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Array;
@@ -115,6 +120,7 @@
// message codes
static final int MESSAGE_TIMEOUT = 2;
+ static final int MESSAGE_SAVE_POLICY_FILE = 3;
static final int LONG_DELAY = 3500; // 3.5 seconds
static final int SHORT_DELAY = 2000; // 2 seconds
@@ -209,15 +215,6 @@
private final NotificationUsageStats mUsageStats = new NotificationUsageStats();
- private int mZenMode;
- // temporary, until we update apps to provide metadata
- private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
- "com.google.android.dialer",
- "com.android.phone"
- ));
- private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
- "com.google.android.deskclock"
- ));
private static final String EXTRA_INTERCEPT = "android.intercept";
// Profiles of the current user.
@@ -421,53 +418,82 @@
Archive mArchive = new Archive();
- private void loadBlockDb() {
- synchronized(mBlockedPackages) {
- if (mPolicyFile == null) {
- File dir = new File("/data/system");
- mPolicyFile = new AtomicFile(new File(dir, "notification_policy.xml"));
+ private void loadPolicyFile() {
+ synchronized(mPolicyFile) {
+ mBlockedPackages.clear();
- mBlockedPackages.clear();
+ FileInputStream infile = null;
+ try {
+ infile = mPolicyFile.openRead();
+ final XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(infile, null);
- FileInputStream infile = null;
- try {
- infile = mPolicyFile.openRead();
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(infile, null);
-
- int type;
- String tag;
- int version = DB_VERSION;
- while ((type = parser.next()) != END_DOCUMENT) {
- tag = parser.getName();
- if (type == START_TAG) {
- if (TAG_BODY.equals(tag)) {
- version = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VERSION));
- } else if (TAG_BLOCKED_PKGS.equals(tag)) {
- while ((type = parser.next()) != END_DOCUMENT) {
- tag = parser.getName();
- if (TAG_PACKAGE.equals(tag)) {
- mBlockedPackages.add(
- parser.getAttributeValue(null, ATTR_NAME));
- } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
- break;
- }
+ int type;
+ String tag;
+ int version = DB_VERSION;
+ while ((type = parser.next()) != END_DOCUMENT) {
+ tag = parser.getName();
+ if (type == START_TAG) {
+ if (TAG_BODY.equals(tag)) {
+ version = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VERSION));
+ } else if (TAG_BLOCKED_PKGS.equals(tag)) {
+ while ((type = parser.next()) != END_DOCUMENT) {
+ tag = parser.getName();
+ if (TAG_PACKAGE.equals(tag)) {
+ mBlockedPackages.add(
+ parser.getAttributeValue(null, ATTR_NAME));
+ } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
+ break;
}
}
}
}
- } catch (FileNotFoundException e) {
- // No data yet
- } catch (IOException e) {
- Log.wtf(TAG, "Unable to read blocked notifications database", e);
- } catch (NumberFormatException e) {
- Log.wtf(TAG, "Unable to parse blocked notifications database", e);
- } catch (XmlPullParserException e) {
- Log.wtf(TAG, "Unable to parse blocked notifications database", e);
- } finally {
- IoUtils.closeQuietly(infile);
+ mZenModeHelper.readXml(parser);
}
+ } catch (FileNotFoundException e) {
+ // No data yet
+ } catch (IOException e) {
+ Log.wtf(TAG, "Unable to read notification policy", e);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Unable to parse notification policy", e);
+ } catch (XmlPullParserException e) {
+ Log.wtf(TAG, "Unable to parse notification policy", e);
+ } finally {
+ IoUtils.closeQuietly(infile);
+ }
+ }
+ }
+
+ public void savePolicyFile() {
+ mHandler.removeMessages(MESSAGE_SAVE_POLICY_FILE);
+ mHandler.sendEmptyMessage(MESSAGE_SAVE_POLICY_FILE);
+ }
+
+ private void handleSavePolicyFile() {
+ Slog.d(TAG, "handleSavePolicyFile");
+ synchronized (mPolicyFile) {
+ final FileOutputStream stream;
+ try {
+ stream = mPolicyFile.startWrite();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save policy file", e);
+ return;
+ }
+
+ try {
+ final XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, "utf-8");
+ out.startDocument(null, true);
+ out.startTag(null, TAG_BODY);
+ out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
+ mZenModeHelper.writeXml(out);
+ out.endTag(null, TAG_BODY);
+ out.endDocument();
+ mPolicyFile.finishWrite(stream);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save policy file, restoring backup", e);
+ mPolicyFile.failWrite(stream);
}
}
}
@@ -1066,10 +1092,7 @@
@Override
public boolean allowDisable(int what, IBinder token, String pkg) {
- if (isCall(pkg, null)) {
- return mZenMode == Settings.Global.ZEN_MODE_OFF;
- }
- return true;
+ return mZenModeHelper.allowDisable(what, token, pkg);
}
@Override
@@ -1194,9 +1217,6 @@
private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
= Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
- private final Uri ZEN_MODE
- = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
-
SettingsObserver(Handler handler) {
super(handler);
}
@@ -1207,8 +1227,6 @@
false, this, UserHandle.USER_ALL);
resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
false, this, UserHandle.USER_ALL);
- resolver.registerContentObserver(ZEN_MODE,
- false, this);
update(null);
}
@@ -1229,13 +1247,11 @@
if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
rebindListenerServices();
}
- if (ZEN_MODE.equals(uri)) {
- updateZenMode();
- }
}
}
private SettingsObserver mSettingsObserver;
+ private ZenModeHelper mZenModeHelper;
static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) {
int[] ar = r.getIntArray(resid);
@@ -1261,6 +1277,15 @@
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mHandler = new WorkerHandler();
+ mZenModeHelper = new ZenModeHelper(getContext(), mHandler);
+ mZenModeHelper.setCallback(new ZenModeHelper.Callback() {
+ @Override
+ public void onConfigChanged() {
+ savePolicyFile();
+ }
+ });
+ final File systemDir = new File(Environment.getDataDirectory(), "system");
+ mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
importOldBlockDb();
@@ -1297,7 +1322,7 @@
Settings.Global.DEVICE_PROVISIONED, 0)) {
mDisableNotificationAlerts = true;
}
- updateZenMode();
+ mZenModeHelper.updateZenMode();
updateCurrentProfilesCache(getContext());
@@ -1350,7 +1375,7 @@
* Read the old XML-based app block database and import those blockages into the AppOps system.
*/
private void importOldBlockDb() {
- loadBlockDb();
+ loadPolicyFile();
PackageManager pm = getContext().getPackageManager();
for (String pkg : mBlockedPackages) {
@@ -1363,9 +1388,6 @@
}
}
mBlockedPackages.clear();
- if (mPolicyFile != null) {
- mPolicyFile.delete();
- }
}
@Override
@@ -1745,6 +1767,18 @@
}
@Override
+ public ZenModeConfig getZenModeConfig() {
+ checkCallerIsSystem();
+ return mZenModeHelper.getConfig();
+ }
+
+ @Override
+ public boolean setZenModeConfig(ZenModeConfig config) {
+ checkCallerIsSystem();
+ return mZenModeHelper.setConfig(config);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -1825,7 +1859,6 @@
pw.println(" mSoundNotification=" + mSoundNotification);
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisableNotificationAlerts=" + mDisableNotificationAlerts);
- pw.println(" mZenMode=" + Settings.Global.zenModeToString(mZenMode));
pw.println(" mSystemReady=" + mSystemReady);
pw.println(" mArchive=" + mArchive.toString());
Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
@@ -1841,6 +1874,8 @@
pw.println("\n Usage Stats:");
mUsageStats.dump(pw, " ");
+ pw.println("\n Zen Mode:");
+ mZenModeHelper.dump(pw, " ");
}
}
@@ -1973,7 +2008,7 @@
}
// Is this notification intercepted by zen mode?
- final boolean intercept = shouldIntercept(pkg, notification);
+ final boolean intercept = mZenModeHelper.shouldIntercept(pkg, notification);
notification.extras.putBoolean(EXTRA_INTERCEPT, intercept);
// Should this notification make noise, vibe, or use the LED?
@@ -2358,6 +2393,9 @@
case MESSAGE_TIMEOUT:
handleTimeout((ToastRecord)msg.obj);
break;
+ case MESSAGE_SAVE_POLICY_FILE:
+ handleSavePolicyFile();
+ break;
}
}
}
@@ -2722,42 +2760,6 @@
}
}
- private void updateZenMode() {
- final int mode = Settings.Global.getInt(getContext().getContentResolver(),
- Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
- if (mode != mZenMode) {
- Slog.d(TAG, String.format("updateZenMode: %s -> %s",
- Settings.Global.zenModeToString(mZenMode),
- Settings.Global.zenModeToString(mode)));
- }
- mZenMode = mode;
-
- final String[] exceptionPackages = null; // none (for now)
-
- // call restrictions
- final boolean muteCalls = mZenMode != Settings.Global.ZEN_MODE_OFF;
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_RING,
- muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_RING,
- muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
-
- // alarm restrictions
- final boolean muteAlarms = false; // TODO until we save user config
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_ALARM,
- muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_ALARM,
- muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
-
- // restrict vibrations with no hints
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.USE_DEFAULT_STREAM_TYPE,
- (muteAlarms || muteCalls) ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- }
-
private void updateCurrentProfilesCache(Context context) {
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (userManager != null) {
@@ -2788,19 +2790,4 @@
return mCurrentProfiles.get(userId) != null;
}
}
-
- private boolean isCall(String pkg, Notification n) {
- return CALL_PACKAGES.contains(pkg);
- }
-
- private boolean isAlarm(String pkg, Notification n) {
- return ALARM_PACKAGES.contains(pkg);
- }
-
- private boolean shouldIntercept(String pkg, Notification n) {
- if (mZenMode != Settings.Global.ZEN_MODE_OFF) {
- return !isAlarm(pkg, n);
- }
- return false;
- }
}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
new file mode 100644
index 0000000..80f5b5c
--- /dev/null
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -0,0 +1,312 @@
+/**
+ * Copyright (c) 2014, 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.notification;
+
+import android.app.AlarmManager;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * NotificationManagerService helper for functionality related to zen mode.
+ */
+public class ZenModeHelper {
+ private static final String TAG = "ZenModeHelper";
+
+ private static final String ACTION_ENTER_ZEN = "enter_zen";
+ private static final int REQUEST_CODE_ENTER = 100;
+ private static final String ACTION_EXIT_ZEN = "exit_zen";
+ private static final int REQUEST_CODE_EXIT = 101;
+ private static final String EXTRA_TIME = "time";
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final SettingsObserver mSettingsObserver;
+ private final AppOpsManager mAppOps;
+ private final ZenModeConfig mDefaultConfig;
+
+ private Callback mCallback;
+ private int mZenMode;
+ private ZenModeConfig mConfig;
+
+ // temporary, until we update apps to provide metadata
+ private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
+ "com.google.android.dialer",
+ "com.android.phone"
+ ));
+ private static final Set<String> MESSAGE_PACKAGES = new HashSet<String>(Arrays.asList(
+ "com.google.android.talk",
+ "com.android.mms"
+ ));
+
+ public ZenModeHelper(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mDefaultConfig = readDefaultConfig(context.getResources());
+ mConfig = mDefaultConfig;
+ mSettingsObserver = new SettingsObserver(mHandler);
+ mSettingsObserver.observe();
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_ENTER_ZEN);
+ filter.addAction(ACTION_EXIT_ZEN);
+ mContext.registerReceiver(new ZenBroadcastReceiver(), filter);
+ }
+
+ public static ZenModeConfig readDefaultConfig(Resources resources) {
+ XmlResourceParser parser = null;
+ try {
+ parser = resources.getXml(R.xml.default_zen_mode_config);
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ final ZenModeConfig config = ZenModeConfig.readXml(parser);
+ if (config != null) return config;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Error reading default zen mode config from resource", e);
+ } finally {
+ IoUtils.closeQuietly(parser);
+ }
+ return new ZenModeConfig();
+ }
+
+ public void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ public boolean shouldIntercept(String pkg, Notification n) {
+ if (mZenMode != Global.ZEN_MODE_OFF) {
+ if (isCall(pkg, n)) {
+ return !mConfig.allowCalls;
+ }
+ if (isMessage(pkg, n)) {
+ return !mConfig.allowMessages;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void updateZenMode() {
+ final int mode = Global.getInt(mContext.getContentResolver(),
+ Global.ZEN_MODE, Global.ZEN_MODE_OFF);
+ if (mode != mZenMode) {
+ Slog.d(TAG, String.format("updateZenMode: %s -> %s",
+ Global.zenModeToString(mZenMode),
+ Global.zenModeToString(mode)));
+ }
+ mZenMode = mode;
+ final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
+ final String[] exceptionPackages = null; // none (for now)
+
+ // call restrictions
+ final boolean muteCalls = zen && !mConfig.allowCalls;
+ mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_RING,
+ muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+ exceptionPackages);
+ mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_RING,
+ muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+ exceptionPackages);
+
+ // restrict vibrations with no hints
+ mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.USE_DEFAULT_STREAM_TYPE,
+ zen ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+ exceptionPackages);
+ }
+
+ public boolean allowDisable(int what, IBinder token, String pkg) {
+ if (isCall(pkg, null)) {
+ return mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
+ }
+ return true;
+ }
+
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mZenMode=");
+ pw.println(Global.zenModeToString(mZenMode));
+ pw.print(prefix); pw.print("mConfig="); pw.println(mConfig);
+ pw.print(prefix); pw.print("mDefaultConfig="); pw.println(mDefaultConfig);
+ }
+
+ public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+ final ZenModeConfig config = ZenModeConfig.readXml(parser);
+ if (config != null) {
+ setConfig(config);
+ }
+ }
+
+ public void writeXml(XmlSerializer out) throws IOException {
+ mConfig.writeXml(out);
+ }
+
+ public ZenModeConfig getConfig() {
+ return mConfig;
+ }
+
+ public boolean setConfig(ZenModeConfig config) {
+ if (config == null || !config.isValid()) return false;
+ if (config.equals(mConfig)) return true;
+ mConfig = config;
+ Slog.d(TAG, "mConfig=" + mConfig);
+ if (mCallback != null) mCallback.onConfigChanged();
+ final String val = Integer.toString(mConfig.hashCode());
+ Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
+ updateAlarms();
+ updateZenMode();
+ return true;
+ }
+
+ private boolean isCall(String pkg, Notification n) {
+ return CALL_PACKAGES.contains(pkg);
+ }
+
+ private boolean isMessage(String pkg, Notification n) {
+ return MESSAGE_PACKAGES.contains(pkg);
+ }
+
+ private void updateAlarms() {
+ updateAlarm(ACTION_ENTER_ZEN, REQUEST_CODE_ENTER,
+ mConfig.sleepStartHour, mConfig.sleepStartMinute);
+ updateAlarm(ACTION_EXIT_ZEN, REQUEST_CODE_EXIT,
+ mConfig.sleepEndHour, mConfig.sleepEndMinute);
+ }
+
+ private void updateAlarm(String action, int requestCode, int hr, int min) {
+ final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ final long now = System.currentTimeMillis();
+ final Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(now);
+ c.set(Calendar.HOUR_OF_DAY, hr);
+ c.set(Calendar.MINUTE, min);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ if (c.getTimeInMillis() <= now) {
+ c.add(Calendar.DATE, 1);
+ }
+ final long time = c.getTimeInMillis();
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, requestCode,
+ new Intent(action).putExtra(EXTRA_TIME, time), PendingIntent.FLAG_UPDATE_CURRENT);
+ alarms.cancel(pendingIntent);
+ if (mConfig.sleepMode != null) {
+ Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future, now=%s",
+ action, ts(time), time - now, ts(now)));
+ alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+ }
+ }
+
+ private static String ts(long time) {
+ return new Date(time) + " (" + time + ")";
+ }
+
+ public static boolean isWeekend(long time, int offsetDays) {
+ final Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(time);
+ if (offsetDays != 0) {
+ c.add(Calendar.DATE, offsetDays);
+ }
+ final int day = c.get(Calendar.DAY_OF_WEEK);
+ return day == Calendar.SATURDAY || day == Calendar.SUNDAY;
+ }
+
+ private class SettingsObserver extends ContentObserver {
+ private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
+
+ public SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ public void observe() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
+ update(null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ update(uri);
+ }
+
+ public void update(Uri uri) {
+ if (ZEN_MODE.equals(uri)) {
+ updateZenMode();
+ }
+ }
+ }
+
+ private class ZenBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION_ENTER_ZEN.equals(intent.getAction())) {
+ setZenMode(intent, 1, Global.ZEN_MODE_ON);
+ } else if (ACTION_EXIT_ZEN.equals(intent.getAction())) {
+ setZenMode(intent, 0, Global.ZEN_MODE_OFF);
+ }
+ }
+
+ private void setZenMode(Intent intent, int wkendOffsetDays, int zenModeValue) {
+ final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
+ final long now = System.currentTimeMillis();
+ Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
+ intent.getAction(), ts(schTime), ts(now), now - schTime));
+
+ final boolean skip = ZenModeConfig.SLEEP_MODE_WEEKNIGHTS.equals(mConfig.sleepMode) &&
+ isWeekend(schTime, wkendOffsetDays);
+
+ if (skip) {
+ Slog.d(TAG, "Skipping zen mode update for the weekend");
+ } else {
+ Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zenModeValue);
+ }
+ updateAlarms();
+ }
+ }
+
+ public interface Callback {
+ void onConfigChanged();
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index df69a6e..702d9d2 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4492,17 +4492,6 @@
// writer
synchronized (mPackages) {
- if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
- // Check all shared libraries and map to their actual file path.
- // We only do this here for apps not on a system dir, because those
- // are the only ones that can fail an install due to this. We
- // will take care of the system apps by updating all of their
- // library paths after the scan is done.
- if (!updateSharedLibrariesLPw(pkg, null)) {
- return null;
- }
- }
-
if (pkg.mSharedUserId != null) {
suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
if (suid == null) {
@@ -4613,6 +4602,17 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
+ if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ // Check all shared libraries and map to their actual file path.
+ // We only do this here for apps not on a system dir, because those
+ // are the only ones that can fail an install due to this. We
+ // will take care of the system apps by updating all of their
+ // library paths after the scan is done.
+ if (!updateSharedLibrariesLPw(pkg, null)) {
+ return null;
+ }
+ }
+
if (mFoundPolicyFile) {
SELinuxMMAC.assignSeinfoValue(pkg);
}
@@ -5420,6 +5420,37 @@
}
}
+ private String calculateApkRoot(final File codePath) {
+ final File codeRoot;
+ if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
+ codeRoot = Environment.getRootDirectory();
+ } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) {
+ codeRoot = Environment.getRootDirectory();
+ } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
+ codeRoot = Environment.getVendorDirectory();
+ } else {
+ // Unrecognized code path; take its top real segment as the apk root:
+ // e.g. /something/app/blah.apk => /something
+ try {
+ File f = codePath.getCanonicalFile();
+ File parent = f.getParentFile(); // non-null because codePath is a file
+ File tmp;
+ while ((tmp = parent.getParentFile()) != null) {
+ f = parent;
+ parent = tmp;
+ }
+ codeRoot = f;
+ Slog.w(TAG, "Unrecognized code path "
+ + codePath + " - using " + codeRoot);
+ } catch (IOException e) {
+ // Can't canonicalize the lib path -- shenanigans?
+ Slog.w(TAG, "Can't canonicalize code path " + codePath);
+ return Environment.getRootDirectory().getPath();
+ }
+ }
+ return codeRoot.getPath();
+ }
+
// This is the initial scan-time determination of how to handle a given
// package for purposes of native library location.
private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
@@ -5431,11 +5462,10 @@
if (bundledApk) {
// If "/system/lib64/apkname" exists, assume that is the per-package
// native library directory to use; otherwise use "/system/lib/apkname".
- File lib64 = new File(Environment.getRootDirectory(), LIB64_DIR_NAME);
+ String apkRoot = calculateApkRoot(pkgSetting.codePath);
+ File lib64 = new File(apkRoot, LIB64_DIR_NAME);
File packLib64 = new File(lib64, apkName);
- libDir = (packLib64.exists())
- ? lib64
- : new File(Environment.getRootDirectory(), LIB_DIR_NAME);
+ libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
} else {
libDir = mAppLibInstallDir;
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a6e83a7..53db9ef 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -22,6 +22,7 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
+import android.app.admin.DevicePolicyManager;
import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -437,7 +438,7 @@
@Override
public void setUserRestrictions(Bundle restrictions, int userId) {
- checkManageUsersPermission("setUserRestrictions");
+ checkProfileOwnerOrManageUsersPermission("setUserRestrictions");
if (restrictions == null) return;
synchronized (mPackagesLock) {
@@ -463,16 +464,53 @@
* @param message used as message if SecurityException is thrown
* @throws SecurityException if the caller is not system or root
*/
- private static final void checkManageUsersPermission(String message) {
+ private final void checkManageUsersPermission(String message) {
final int uid = Binder.getCallingUid();
- if (uid != Process.SYSTEM_UID && uid != 0
- && ActivityManager.checkComponentPermission(
- android.Manifest.permission.MANAGE_USERS,
- uid, -1, true) != PackageManager.PERMISSION_GRANTED) {
+
+ if (missingManageUsersPermission(uid)) {
throw new SecurityException("You need MANAGE_USERS permission to: " + message);
}
}
+ /**
+ * Enforces that only the system UID, root's UID, apps that have the
+ * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
+ * permission, the profile owner, or the device owner can make certain calls to the
+ * UserManager.
+ *
+ * @param message used as message if SecurityException is thrown
+ * @throws SecurityException if the caller is not system, root, or device
+ * owner
+ */
+ private final void checkProfileOwnerOrManageUsersPermission(String message) {
+ final int uid = Binder.getCallingUid();
+ boolean isProfileOwner = false;
+ if (mContext != null && mContext.getPackageManager() != null) {
+ String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ if (dpm != null) {
+ for (String pkg : pkgs) {
+ if (dpm.isDeviceOwnerApp(pkg) || dpm.isProfileOwnerApp(pkg)) {
+ isProfileOwner = true;
+ }
+ }
+ }
+ }
+
+ if (missingManageUsersPermission(uid) && !isProfileOwner) {
+ throw new SecurityException(
+ "You need MANAGE_USERS permission or device owner privileges to: " + message);
+ }
+ }
+
+ private boolean missingManageUsersPermission(int uid) {
+ return uid != Process.SYSTEM_UID && uid != 0
+ && ActivityManager.checkComponentPermission(
+ android.Manifest.permission.MANAGE_USERS,
+ uid, -1, true) != PackageManager.PERMISSION_GRANTED;
+ }
+
private void writeBitmapLocked(UserInfo info, Bitmap bitmap) {
try {
File dir = new File(mUsersDir, Integer.toString(info.id));
@@ -1175,7 +1213,8 @@
public Bundle getApplicationRestrictionsForUser(String packageName, int userId) {
if (UserHandle.getCallingUserId() != userId
|| !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
- checkManageUsersPermission("Only system can get restrictions for other users/apps");
+ checkProfileOwnerOrManageUsersPermission(
+ "Only system or device owner can get restrictions for other users/apps");
}
synchronized (mPackagesLock) {
// Read the restrictions from XML
@@ -1188,7 +1227,8 @@
int userId) {
if (UserHandle.getCallingUserId() != userId
|| !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
- checkManageUsersPermission("Only system can set restrictions for other users/apps");
+ checkProfileOwnerOrManageUsersPermission(
+ "Only system or device owner can set restrictions for other users/apps");
}
synchronized (mPackagesLock) {
// Write the restrictions to XML
@@ -1290,7 +1330,8 @@
@Override
public void removeRestrictions() {
- checkManageUsersPermission("Only system can remove restrictions");
+ checkProfileOwnerOrManageUsersPermission(
+ "Only system or device owner can remove restrictions");
final int userHandle = UserHandle.getCallingUserId();
removeRestrictionsForUser(userHandle, true);
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 82cef7f..cfe24fe 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -168,6 +168,10 @@
// Poll interval in milliseconds for watching boot animation finished.
private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
+ //powerHint
+ private static final int POWER_HINT_LOW_POWER_MODE = 5;
+ private static boolean mLowPowerModeEnabled;
+
private final Context mContext;
private LightsManager mLightsManager;
private BatteryService mBatteryService;
@@ -530,7 +534,9 @@
resolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.SCREEN_BRIGHTNESS_MODE),
false, mSettingsObserver, UserHandle.USER_ALL);
-
+ resolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.LOW_POWER_MODE),
+ false, mSettingsObserver, UserHandle.USER_ALL);
// Go.
readConfigurationLocked();
updateSettingsLocked();
@@ -610,6 +616,14 @@
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
+ boolean mIsEnabled = Settings.Global.getInt(resolver,
+ Settings.Global.LOW_POWER_MODE, 0) != 0;
+ if (mIsEnabled != mLowPowerModeEnabled) {
+ BinderService bs = new BinderService();
+ bs.powerHint(POWER_HINT_LOW_POWER_MODE, mIsEnabled ? 1 : 0);
+ mLowPowerModeEnabled = mIsEnabled;
+ }
+
mDirty |= DIRTY_SETTINGS;
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 75e5857..6700895 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -26,6 +26,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
@@ -42,6 +43,7 @@
import android.tv.TvInputService;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Surface;
@@ -116,17 +118,19 @@
UserState userState = getUserStateLocked(userId);
userState.inputList.clear();
+ if (DEBUG) Slog.d(TAG, "buildTvInputList");
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> services = pm.queryIntentServices(
new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
for (ResolveInfo ri : services) {
ServiceInfo si = ri.serviceInfo;
if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
- Log.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
+ Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
+ android.Manifest.permission.BIND_TV_INPUT);
continue;
}
TvInputInfo info = new TvInputInfo(ri);
+ if (DEBUG) Slog.d(TAG, "add " + info.getId());
userState.inputList.add(info);
}
}
@@ -161,7 +165,7 @@
try {
state.session.release();
} catch (RemoteException e) {
- Log.e(TAG, "error in release", e);
+ Slog.e(TAG, "error in release", e);
}
}
}
@@ -173,7 +177,7 @@
try {
serviceState.service.unregisterCallback(serviceState.callback);
} catch (RemoteException e) {
- Log.e(TAG, "error in unregisterCallback", e);
+ Slog.e(TAG, "error in unregisterCallback", e);
}
}
serviceState.clients.clear();
@@ -244,7 +248,7 @@
return;
}
if (DEBUG) {
- Log.i(TAG, "bindServiceAsUser(name=" + name.getClassName() + ", userId=" + userId
+ Slog.d(TAG, "bindServiceAsUser(name=" + name.getClassName() + ", userId=" + userId
+ ")");
}
Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(name);
@@ -255,7 +259,7 @@
// This means that the service is already connected but its state indicates that we have
// nothing to do with it. Then, disconnect the service.
if (DEBUG) {
- Log.i(TAG, "unbindService(name=" + name.getClassName() + ")");
+ Slog.d(TAG, "unbindService(name=" + name.getClassName() + ")");
}
mContext.unbindService(serviceState.connection);
userState.serviceStateMap.remove(name);
@@ -267,7 +271,7 @@
final SessionState sessionState =
getUserStateLocked(userId).sessionStateMap.get(sessionToken);
if (DEBUG) {
- Log.d(TAG, "createSessionInternalLocked(name=" + sessionState.name.getClassName()
+ Slog.d(TAG, "createSessionInternalLocked(name=" + sessionState.name.getClassName()
+ ")");
}
// Set up a callback to send the session token.
@@ -275,7 +279,7 @@
@Override
public void onSessionCreated(ITvInputSession session) {
if (DEBUG) {
- Log.d(TAG, "onSessionCreated(name=" + sessionState.name.getClassName() + ")");
+ Slog.d(TAG, "onSessionCreated(name=" + sessionState.name.getClassName() + ")");
}
synchronized (mLock) {
sessionState.session = session;
@@ -295,7 +299,7 @@
try {
service.createSession(callback);
} catch (RemoteException e) {
- Log.e(TAG, "error in createSession", e);
+ Slog.e(TAG, "error in createSession", e);
removeSessionStateLocked(sessionToken, userId);
sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
sessionState.seq, userId);
@@ -307,7 +311,7 @@
try {
client.onSessionCreated(name, sessionToken, seq);
} catch (RemoteException exception) {
- Log.e(TAG, "error in onSessionCreated", exception);
+ Slog.e(TAG, "error in onSessionCreated", exception);
}
if (sessionToken == null) {
@@ -396,7 +400,7 @@
try {
serviceState.service.registerCallback(serviceState.callback);
} catch (RemoteException e) {
- Log.e(TAG, "error in registerCallback", e);
+ Slog.e(TAG, "error in registerCallback", e);
}
} else {
updateServiceConnectionLocked(name, resolvedUserId);
@@ -432,7 +436,7 @@
try {
serviceState.service.unregisterCallback(serviceState.callback);
} catch (RemoteException e) {
- Log.e(TAG, "error in unregisterCallback", e);
+ Slog.e(TAG, "error in unregisterCallback", e);
} finally {
serviceState.callback = null;
updateServiceConnectionLocked(name, resolvedUserId);
@@ -493,7 +497,7 @@
try {
getSessionLocked(sessionToken, callingUid, resolvedUserId).release();
} catch (RemoteException e) {
- Log.e(TAG, "error in release", e);
+ Slog.e(TAG, "error in release", e);
}
removeSessionStateLocked(sessionToken, resolvedUserId);
@@ -515,7 +519,7 @@
getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface(
surface);
} catch (RemoteException e) {
- Log.e(TAG, "error in setSurface", e);
+ Slog.e(TAG, "error in setSurface", e);
}
}
} finally {
@@ -535,7 +539,7 @@
getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume(
volume);
} catch (RemoteException e) {
- Log.e(TAG, "error in setVolume", e);
+ Slog.e(TAG, "error in setVolume", e);
}
}
} finally {
@@ -551,13 +555,10 @@
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- SessionState sessionState = getUserStateLocked(resolvedUserId)
- .sessionStateMap.get(sessionToken);
- final String serviceName = sessionState.name.getClassName();
try {
getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri);
} catch (RemoteException e) {
- Log.e(TAG, "error in tune", e);
+ Slog.e(TAG, "error in tune", e);
return;
}
}
@@ -565,6 +566,67 @@
Binder.restoreCallingIdentity(identity);
}
}
+
+ @Override
+ public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame,
+ int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "createOverlayView");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .createOverlayView(windowToken, frame);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in createOverlayView", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "relayoutOverlayView");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .relayoutOverlayView(frame);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in relayoutOverlayView", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void removeOverlayView(IBinder sessionToken, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "removeOverlayView");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .removeOverlayView();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in removeOverlayView", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
}
private static final class UserState {
@@ -621,7 +683,7 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) {
- Log.d(TAG, "onServiceConnected(name=" + name.getClassName() + ")");
+ Slog.d(TAG, "onServiceConnected(name=" + name.getClassName() + ")");
}
synchronized (mLock) {
ServiceState serviceState = getServiceStateLocked(name, mUserId);
@@ -633,7 +695,7 @@
try {
serviceState.service.registerCallback(serviceState.callback);
} catch (RemoteException e) {
- Log.e(TAG, "error in registerCallback", e);
+ Slog.e(TAG, "error in registerCallback", e);
}
}
@@ -647,7 +709,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) {
- Log.d(TAG, "onServiceDisconnected(name=" + name.getClassName() + ")");
+ Slog.d(TAG, "onServiceDisconnected(name=" + name.getClassName() + ")");
}
}
}
@@ -663,7 +725,7 @@
public void onAvailabilityChanged(ComponentName name, boolean isAvailable)
throws RemoteException {
if (DEBUG) {
- Log.d(TAG, "onAvailabilityChanged(name=" + name.getClassName() + ", isAvailable="
+ Slog.d(TAG, "onAvailabilityChanged(name=" + name.getClassName() + ", isAvailable="
+ isAvailable + ")");
}
synchronized (mLock) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 912ac4d..f08d69f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -311,6 +311,7 @@
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
+ NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
IPackageManager pm = null;
WindowManagerService wm = null;
@@ -643,6 +644,14 @@
}
try {
+ Slog.i(TAG, "Network Score Service");
+ networkScore = new NetworkScoreService(context);
+ ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
+ } catch (Throwable e) {
+ reportWtf("starting Network Score Service", e);
+ }
+
+ try {
Slog.i(TAG, "Network Service Discovery Service");
serviceDiscovery = NsdService.create(context);
ServiceManager.addService(
@@ -1021,6 +1030,7 @@
final NetworkStatsService networkStatsF = networkStats;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
+ final NetworkScoreService networkScoreF = networkScore;
final DockObserver dockF = dock;
final WallpaperManagerService wallpaperF = wallpaper;
final InputMethodManagerService immF = imm;
@@ -1069,6 +1079,11 @@
reportWtf("making Battery Service ready", e);
}
try {
+ if (networkScoreF != null) networkScoreF.systemReady();
+ } catch (Throwable e) {
+ reportWtf("making Network Score Service ready", e);
+ }
+ try {
if (networkManagementF != null) networkManagementF.systemReady();
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index d2eccbe..ebe1bed 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -42,6 +42,15 @@
} Command;
/*
+ * Pseudolocalization methods
+ */
+typedef enum PseudolocalizationMethod {
+ NO_PSEUDOLOCALIZATION = 0,
+ PSEUDO_ACCENTED,
+ PSEUDO_BIDI,
+} PseudolocalizationMethod;
+
+/*
* Bundle of goodies, including everything specified on the command line.
*/
class Bundle {
@@ -50,7 +59,7 @@
: mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false),
mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
mUpdate(false), mExtending(false),
- mRequireLocalization(false), mPseudolocalize(false),
+ mRequireLocalization(false), mPseudolocalize(NO_PSEUDOLOCALIZATION),
mWantUTF16(false), mValues(false), mIncludeMetaData(false),
mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
@@ -95,8 +104,8 @@
void setExtending(bool val) { mExtending = val; }
bool getRequireLocalization(void) const { return mRequireLocalization; }
void setRequireLocalization(bool val) { mRequireLocalization = val; }
- bool getPseudolocalize(void) const { return mPseudolocalize; }
- void setPseudolocalize(bool val) { mPseudolocalize = val; }
+ short getPseudolocalize(void) const { return mPseudolocalize; }
+ void setPseudolocalize(short val) { mPseudolocalize = val; }
void setWantUTF16(bool val) { mWantUTF16 = val; }
bool getValues(void) const { return mValues; }
void setValues(bool val) { mValues = val; }
@@ -259,7 +268,7 @@
bool mUpdate;
bool mExtending;
bool mRequireLocalization;
- bool mPseudolocalize;
+ short mPseudolocalize;
bool mWantUTF16;
bool mValues;
bool mIncludeMetaData;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 44b8340..0af1ce1 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -2048,14 +2048,17 @@
FILE* fp;
String8 dependencyFile;
- // -c zz_ZZ means do pseudolocalization
+ // -c en_XA or/and ar_XB means do pseudolocalization
ResourceFilter filter;
err = filter.parse(bundle->getConfigurations());
if (err != NO_ERROR) {
goto bail;
}
if (filter.containsPseudo()) {
- bundle->setPseudolocalize(true);
+ bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
+ }
+ if (filter.containsPseudoBidi()) {
+ bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
}
N = bundle->getFileSpecCount();
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index e8a2be4..8ca852e 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -24,8 +24,10 @@
String8 part(p, q-p);
- if (part == "zz_ZZ") {
- mContainsPseudo = true;
+ if (part == "en_XA") {
+ mContainsPseudoAccented = true;
+ } else if (part == "ar_XB") {
+ mContainsPseudoBidi = true;
}
int axis;
AxisValue value;
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index 0d127ba..c57770e 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -16,19 +16,22 @@
class ResourceFilter
{
public:
- ResourceFilter() : mData(), mContainsPseudo(false) {}
+ ResourceFilter() : mData(), mContainsPseudoAccented(false),
+ mContainsPseudoBidi(false) {}
status_t parse(const char* arg);
bool isEmpty() const;
bool match(int axis, const ResTable_config& config) const;
bool match(const ResTable_config& config) const;
const SortedVector<AxisValue>* configsForAxis(int axis) const;
- inline bool containsPseudo() const { return mContainsPseudo; }
+ inline bool containsPseudo() const { return mContainsPseudoAccented; }
+ inline bool containsPseudoBidi() const { return mContainsPseudoBidi; }
private:
bool match(int axis, const AxisValue& value) const;
KeyedVector<int,SortedVector<AxisValue> > mData;
- bool mContainsPseudo;
+ bool mContainsPseudoAccented;
+ bool mContainsPseudoBidi;
};
#endif
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 0fb2606..25bb26e 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -25,7 +25,7 @@
if (root == NULL) {
return UNKNOWN_ERROR;
}
-
+
return compileXmlFile(assets, root, target, table, options);
}
@@ -577,13 +577,13 @@
int32_t curFormat,
bool isFormatted,
const String16& product,
- bool pseudolocalize,
+ PseudolocalizationMethod pseudolocalize,
const bool overwrite,
ResourceTable* outTable)
{
status_t err;
const String16 item16("item");
-
+
String16 str;
Vector<StringPool::entry_style_span> spans;
err = parseStyledString(bundle, in->getPrintableSource().string(),
@@ -672,7 +672,7 @@
int32_t curFormat,
bool isFormatted,
const String16& product,
- bool pseudolocalize,
+ PseudolocalizationMethod pseudolocalize,
const bool overwrite,
KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
ResourceTable* outTable)
@@ -854,10 +854,16 @@
ResTable_config curParams(defParams);
ResTable_config pseudoParams(curParams);
- pseudoParams.language[0] = 'z';
- pseudoParams.language[1] = 'z';
- pseudoParams.country[0] = 'Z';
- pseudoParams.country[1] = 'Z';
+ pseudoParams.language[0] = 'e';
+ pseudoParams.language[1] = 'n';
+ pseudoParams.country[0] = 'X';
+ pseudoParams.country[1] = 'A';
+
+ ResTable_config pseudoBidiParams(curParams);
+ pseudoBidiParams.language[0] = 'a';
+ pseudoBidiParams.language[1] = 'r';
+ pseudoBidiParams.country[0] = 'X';
+ pseudoBidiParams.country[1] = 'B';
while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
if (code == ResXMLTree::START_TAG) {
@@ -1334,6 +1340,7 @@
name,
locale,
SourcePos(in->getPrintableSource(), block.getLineNumber()));
+ curIsPseudolocalizable = fileIsTranslatable;
}
if (formatted == false16) {
@@ -1389,6 +1396,7 @@
curTag = &plurals16;
curType = plurals16;
curIsBag = true;
+ curIsPseudolocalizable = fileIsTranslatable;
} else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
curTag = &array16;
curType = array16;
@@ -1410,26 +1418,24 @@
} else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
// Check whether these strings need valid formats.
// (simplified form of what string16 does above)
+ bool isTranslatable = false;
size_t n = block.getAttributeCount();
// Pseudolocalizable by default, unless this string array isn't
// translatable.
- curIsPseudolocalizable = true;
for (size_t i = 0; i < n; i++) {
size_t length;
const uint16_t* attr = block.getAttributeName(i, &length);
- if (strcmp16(attr, translatable16.string()) == 0) {
- const uint16_t* value = block.getAttributeStringValue(i, &length);
- if (strcmp16(value, false16.string()) == 0) {
- curIsPseudolocalizable = false;
- }
- }
-
if (strcmp16(attr, formatted16.string()) == 0) {
const uint16_t* value = block.getAttributeStringValue(i, &length);
if (strcmp16(value, false16.string()) == 0) {
curIsFormatted = false;
}
+ } else if (strcmp16(attr, translatable16.string()) == 0) {
+ const uint16_t* value = block.getAttributeStringValue(i, &length);
+ if (strcmp16(value, false16.string()) == 0) {
+ isTranslatable = false;
+ }
}
}
@@ -1438,6 +1444,7 @@
curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
curIsBag = true;
curIsBagReplaceOnOverwrite = true;
+ curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
} else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
curTag = &integer_array16;
curType = array16;
@@ -1559,19 +1566,29 @@
err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
ident, parentIdent, itemIdent, curFormat, curIsFormatted,
- product, false, overwrite, outTable);
+ product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
- && bundle->getPseudolocalize()) {
+ && bundle->getPseudolocalize() > 0) {
// pseudolocalize here
-#if 1
- block.setPosition(parserPosition);
- err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
- curType, ident, parentIdent, itemIdent, curFormat,
- curIsFormatted, product, true, overwrite, outTable);
-#endif
+ if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
+ PSEUDO_ACCENTED) {
+ block.setPosition(parserPosition);
+ err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
+ curType, ident, parentIdent, itemIdent, curFormat,
+ curIsFormatted, product, PSEUDO_ACCENTED,
+ overwrite, outTable);
+ }
+ if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
+ PSEUDO_BIDI) {
+ block.setPosition(parserPosition);
+ err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
+ curType, ident, parentIdent, itemIdent, curFormat,
+ curIsFormatted, product, PSEUDO_BIDI,
+ overwrite, outTable);
+ }
}
- }
+ }
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -1592,20 +1609,31 @@
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
- product, false, overwrite, &skippedResourceNames, outTable);
+ product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
}
else if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
- && bundle->getPseudolocalize()) {
+ && bundle->getPseudolocalize() > 0) {
// pseudolocalize here
- block.setPosition(parserPosition);
- err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
- ident, *curTag, curIsStyled, curFormat,
- curIsFormatted, product,
- true, overwrite, &skippedResourceNames, outTable);
+ if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
+ PSEUDO_ACCENTED) {
+ block.setPosition(parserPosition);
+ err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
+ ident, *curTag, curIsStyled, curFormat,
+ curIsFormatted, product,
+ PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
+ }
+ if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
+ PSEUDO_BIDI) {
+ block.setPosition(parserPosition);
+ err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
+ myPackage, curType, ident, *curTag, curIsStyled, curFormat,
+ curIsFormatted, product,
+ PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
+ }
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}
@@ -2637,8 +2665,8 @@
continue;
}
- // don't bother with the pseudolocale "zz_ZZ"
- if (config != "zz_ZZ") {
+ // don't bother with the pseudolocale "en_XA" or "ar_XB"
+ if (config != "en_XA" && config != "ar_XB") {
if (configSrcMap.find(config) == configSrcMap.end()) {
// okay, no specific localization found. it's possible that we are
// requiring a specific regional localization [e.g. de_DE] but there is an
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index a663ad5..607d419 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -187,7 +187,7 @@
String16* outString,
Vector<StringPool::entry_style_span>* outSpans,
bool isFormatted,
- bool pseudolocalize)
+ PseudolocalizationMethod pseudolocalize)
{
Vector<StringPool::entry_style_span> spanStack;
String16 curString;
@@ -198,21 +198,30 @@
size_t len;
ResXMLTree::event_code_t code;
+ // Bracketing if pseudolocalization accented method specified.
+ if (pseudolocalize == PSEUDO_ACCENTED) {
+ curString.append(String16(String8("[")));
+ }
while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
-
if (code == ResXMLTree::TEXT) {
String16 text(inXml->getText(&len));
if (firstTime && text.size() > 0) {
firstTime = false;
if (text.string()[0] == '@') {
// If this is a resource reference, don't do the pseudoloc.
- pseudolocalize = false;
+ pseudolocalize = NO_PSEUDOLOCALIZATION;
}
}
- if (xliffDepth == 0 && pseudolocalize) {
- std::string orig(String8(text).string());
- std::string pseudo = pseudolocalize_string(orig);
- curString.append(String16(String8(pseudo.c_str())));
+ if (xliffDepth == 0 && pseudolocalize > 0) {
+ String16 pseudo;
+ if (pseudolocalize == PSEUDO_ACCENTED) {
+ pseudo = pseudolocalize_string(text);
+ } else if (pseudolocalize == PSEUDO_BIDI) {
+ pseudo = pseudobidi_string(text);
+ } else {
+ pseudo = text;
+ }
+ curString.append(pseudo);
} else {
if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
return UNKNOWN_ERROR;
@@ -352,6 +361,25 @@
}
}
+ // Bracketing if pseudolocalization accented method specified.
+ if (pseudolocalize == PSEUDO_ACCENTED) {
+ const char16_t* str = outString->string();
+ const char16_t* p = str;
+ const char16_t* e = p + outString->size();
+ int words_cnt = 0;
+ while (p < e) {
+ if (isspace(*p)) {
+ words_cnt++;
+ }
+ p++;
+ }
+ unsigned int length = words_cnt > 3 ? outString->size() :
+ outString->size() / 2;
+ curString.append(String16(String8(" ")));
+ curString.append(pseudo_generate_expansion(length));
+ curString.append(String16(String8("]")));
+ }
+
if (code == ResXMLTree::BAD_DOCUMENT) {
SourcePos(String8(fileName), inXml->getLineNumber()).error(
"Error parsing XML\n");
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 05624b7..ccbf9f4 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -26,7 +26,7 @@
String16* outString,
Vector<StringPool::entry_style_span>* outSpans,
bool isFormatted,
- bool isPseudolocalizable);
+ PseudolocalizationMethod isPseudolocalizable);
void printXMLBlock(ResXMLTree* block);
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 9e50c5a..60aa2b2 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -2,89 +2,155 @@
using namespace std;
+// String basis to generate expansion
+static const String16 k_expansion_string = String16("one two three "
+ "four five six seven eight nine ten eleven twelve thirteen "
+ "fourteen fiveteen sixteen seventeen nineteen twenty");
+
+// Special unicode characters to override directionality of the words
+static const String16 k_rlm = String16("\xe2\x80\x8f");
+static const String16 k_rlo = String16("\xE2\x80\xae");
+static const String16 k_pdf = String16("\xE2\x80\xac");
+
+// Placeholder marks
+static const String16 k_placeholder_open = String16("\xc2\xbb");
+static const String16 k_placeholder_close = String16("\xc2\xab");
+
static const char*
-pseudolocalize_char(char c)
+pseudolocalize_char(const char16_t c)
{
switch (c) {
- case 'a': return "\xc4\x83";
- case 'b': return "\xcf\x84";
- case 'c': return "\xc4\x8b";
- case 'd': return "\xc4\x8f";
- case 'e': return "\xc4\x99";
+ case 'a': return "\xc3\xa5";
+ case 'b': return "\xc9\x93";
+ case 'c': return "\xc3\xa7";
+ case 'd': return "\xc3\xb0";
+ case 'e': return "\xc3\xa9";
case 'f': return "\xc6\x92";
case 'g': return "\xc4\x9d";
- case 'h': return "\xd1\x9b";
- case 'i': return "\xcf\x8a";
+ case 'h': return "\xc4\xa5";
+ case 'i': return "\xc3\xae";
case 'j': return "\xc4\xb5";
- case 'k': return "\xc4\xb8";
- case 'l': return "\xc4\xba";
+ case 'k': return "\xc4\xb7";
+ case 'l': return "\xc4\xbc";
case 'm': return "\xe1\xb8\xbf";
- case 'n': return "\xd0\xb8";
- case 'o': return "\xcf\x8c";
- case 'p': return "\xcf\x81";
+ case 'n': return "\xc3\xb1";
+ case 'o': return "\xc3\xb6";
+ case 'p': return "\xc3\xbe";
case 'q': return "\x51";
- case 'r': return "\xd2\x91";
+ case 'r': return "\xc5\x95";
case 's': return "\xc5\xa1";
- case 't': return "\xd1\x82";
- case 'u': return "\xce\xb0";
+ case 't': return "\xc5\xa3";
+ case 'u': return "\xc3\xbb";
case 'v': return "\x56";
- case 'w': return "\xe1\xba\x85";
+ case 'w': return "\xc5\xb5";
case 'x': return "\xd1\x85";
- case 'y': return "\xe1\xbb\xb3";
- case 'z': return "\xc5\xba";
+ case 'y': return "\xc3\xbd";
+ case 'z': return "\xc5\xbe";
case 'A': return "\xc3\x85";
case 'B': return "\xce\xb2";
- case 'C': return "\xc4\x88";
- case 'D': return "\xc4\x90";
- case 'E': return "\xd0\x84";
- case 'F': return "\xce\x93";
- case 'G': return "\xc4\x9e";
- case 'H': return "\xc4\xa6";
- case 'I': return "\xd0\x87";
- case 'J': return "\xc4\xb5";
+ case 'C': return "\xc3\x87";
+ case 'D': return "\xc3\x90";
+ case 'E': return "\xc3\x89";
+ case 'G': return "\xc4\x9c";
+ case 'H': return "\xc4\xa4";
+ case 'I': return "\xc3\x8e";
+ case 'J': return "\xc4\xb4";
case 'K': return "\xc4\xb6";
- case 'L': return "\xc5\x81";
+ case 'L': return "\xc4\xbb";
case 'M': return "\xe1\xb8\xbe";
- case 'N': return "\xc5\x83";
- case 'O': return "\xce\x98";
- case 'P': return "\xcf\x81";
+ case 'N': return "\xc3\x91";
+ case 'O': return "\xc3\x96";
+ case 'P': return "\xc3\x9e";
case 'Q': return "\x71";
- case 'R': return "\xd0\xaf";
- case 'S': return "\xc8\x98";
- case 'T': return "\xc5\xa6";
- case 'U': return "\xc5\xa8";
+ case 'R': return "\xc5\x94";
+ case 'S': return "\xc5\xa0";
+ case 'T': return "\xc5\xa2";
+ case 'U': return "\xc3\x9b";
case 'V': return "\xce\xbd";
- case 'W': return "\xe1\xba\x84";
+ case 'W': return "\xc5\xb4";
case 'X': return "\xc3\x97";
- case 'Y': return "\xc2\xa5";
+ case 'Y': return "\xc3\x9d";
case 'Z': return "\xc5\xbd";
+ case '!': return "\xc2\xa1";
+ case '?': return "\xc2\xbf";
+ case '$': return "\xe2\x82\xac";
default: return NULL;
}
}
+static bool
+is_possible_normal_placeholder_end(const char16_t c) {
+ switch (c) {
+ case 's': return true;
+ case 'S': return true;
+ case 'c': return true;
+ case 'C': return true;
+ case 'd': return true;
+ case 'o': return true;
+ case 'x': return true;
+ case 'X': return true;
+ case 'f': return true;
+ case 'e': return true;
+ case 'E': return true;
+ case 'g': return true;
+ case 'G': return true;
+ case 'a': return true;
+ case 'A': return true;
+ case 'b': return true;
+ case 'B': return true;
+ case 'h': return true;
+ case 'H': return true;
+ case '%': return true;
+ case 'n': return true;
+ default: return false;
+ }
+}
+
+String16
+pseudo_generate_expansion(const unsigned int length) {
+ String16 result = k_expansion_string;
+ const char16_t* s = result.string();
+ if (result.size() < length) {
+ result += String16(" ");
+ result += pseudo_generate_expansion(length - result.size());
+ } else {
+ int ext = 0;
+ // Should contain only whole words, so looking for a space
+ for (unsigned int i = length + 1; i < result.size(); ++i) {
+ ++ext;
+ if (s[i] == ' ') {
+ break;
+ }
+ }
+ result.remove(length + ext, 0);
+ }
+ return result;
+}
+
/**
* Converts characters so they look like they've been localized.
*
* Note: This leaves escape sequences untouched so they can later be
* processed by ResTable::collectString in the normal way.
*/
-string
-pseudolocalize_string(const string& source)
+String16
+pseudolocalize_string(const String16& source)
{
- const char* s = source.c_str();
- string result;
- const size_t I = source.length();
+ const char16_t* s = source.string();
+ String16 result;
+ const size_t I = source.size();
for (size_t i=0; i<I; i++) {
- char c = s[i];
+ char16_t c = s[i];
if (c == '\\') {
+ // Escape syntax, no need to pseudolocalize
if (i<I-1) {
- result += '\\';
+ result += String16("\\");
i++;
c = s[i];
switch (c) {
case 'u':
// this one takes up 5 chars
- result += string(s+i, 5);
+ result += String16(s+i, 5);
i += 4;
break;
case 't':
@@ -96,24 +162,107 @@
case '\'':
case '\\':
default:
- result += c;
+ result.append(&c, 1);
break;
}
} else {
- result += c;
+ result.append(&c, 1);
+ }
+ } else if (c == '%') {
+ // Placeholder syntax, no need to pseudolocalize
+ result += k_placeholder_open;
+ bool end = false;
+ result.append(&c, 1);
+ while (!end && i < I) {
+ ++i;
+ c = s[i];
+ result.append(&c, 1);
+ if (is_possible_normal_placeholder_end(c)) {
+ end = true;
+ } else if (c == 't') {
+ ++i;
+ c = s[i];
+ result.append(&c, 1);
+ end = true;
+ }
+ }
+ result += k_placeholder_close;
+ } else if (c == '<' || c == '&') {
+ // html syntax, no need to pseudolocalize
+ bool tag_closed = false;
+ while (!tag_closed && i < I) {
+ if (c == '&') {
+ String16 escape_text;
+ escape_text.append(&c, 1);
+ bool end = false;
+ size_t htmlCodePos = i;
+ while (!end && htmlCodePos < I) {
+ ++htmlCodePos;
+ c = s[htmlCodePos];
+ escape_text.append(&c, 1);
+ // Valid html code
+ if (c == ';') {
+ end = true;
+ i = htmlCodePos;
+ }
+ // Wrong html code
+ else if (!((c == '#' ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9')))) {
+ end = true;
+ }
+ }
+ result += escape_text;
+ if (escape_text != String16("<")) {
+ tag_closed = true;
+ }
+ continue;
+ }
+ if (c == '>') {
+ tag_closed = true;
+ result.append(&c, 1);
+ continue;
+ }
+ result.append(&c, 1);
+ i++;
+ c = s[i];
}
} else {
+ // This is a pure text that should be pseudolocalized
const char* p = pseudolocalize_char(c);
if (p != NULL) {
- result += p;
+ result += String16(p);
} else {
- result += c;
+ result.append(&c, 1);
}
}
}
-
- //printf("result=\'%s\'\n", result.c_str());
return result;
}
+String16
+pseudobidi_string(const String16& source)
+{
+ const char16_t* s = source.string();
+ String16 result;
+ result += k_rlm;
+ result += k_rlo;
+ for (size_t i=0; i<source.size(); i++) {
+ char16_t c = s[i];
+ switch(c) {
+ case ' ': result += k_pdf;
+ result += k_rlm;
+ result.append(&c, 1);
+ result += k_rlm;
+ result += k_rlo;
+ break;
+ default: result.append(&c, 1);
+ break;
+ }
+ }
+ result += k_pdf;
+ result += k_rlm;
+ return result;
+}
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index 94cb034..e6ab18e 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -1,9 +1,18 @@
#ifndef HOST_PSEUDOLOCALIZE_H
#define HOST_PSEUDOLOCALIZE_H
+#include "StringPool.h"
+
#include <string>
-std::string pseudolocalize_string(const std::string& source);
+String16 pseudolocalize_string(const String16& source);
+// Surrounds every word in the sentance with specific characters that makes
+// the word directionality RTL.
+String16 pseudobidi_string(const String16& source);
+// Generates expansion string based on the specified lenght.
+// Generated string could not be shorter that length, but it could be slightly
+// longer.
+String16 pseudo_generate_expansion(const unsigned int length);
#endif // HOST_PSEUDOLOCALIZE_H
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index ebfe9bc..8862f5b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -355,227 +355,162 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_setConcat(long native_object, long a, long b) {
+ /*package*/ static void native_setConcat(long native_object, long a, long b) {
if (a == native_object) {
- return native_preConcat(native_object, b);
+ native_preConcat(native_object, b);
+ return;
} else if (b == native_object) {
- return native_postConcat(native_object, a);
+ native_postConcat(native_object, a);
+ return;
}
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
Matrix_Delegate a_mtx = sManager.getDelegate(a);
- if (a_mtx == null) {
- return false;
- }
-
Matrix_Delegate b_mtx = sManager.getDelegate(b);
- if (b_mtx == null) {
- return false;
+ if (d != null && a_mtx != null && b_mtx != null) {
+ multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
}
-
- multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
-
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preTranslate(long native_object, float dx, float dy) {
+ /*package*/ static void native_preTranslate(long native_object, float dx, float dy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getTranslate(dx, dy));
}
-
- d.preTransform(getTranslate(dx, dy));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preScale(long native_object, float sx, float sy,
+ /*package*/ static void native_preScale(long native_object, float sx, float sy,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getScale(sx, sy, px, py));
}
-
- d.preTransform(getScale(sx, sy, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preScale(long native_object, float sx, float sy) {
+ /*package*/ static void native_preScale(long native_object, float sx, float sy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getScale(sx, sy));
}
-
- d.preTransform(getScale(sx, sy));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preRotate(long native_object, float degrees,
+ /*package*/ static void native_preRotate(long native_object, float degrees,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getRotate(degrees, px, py));
}
-
- d.preTransform(getRotate(degrees, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preRotate(long native_object, float degrees) {
+ /*package*/ static void native_preRotate(long native_object, float degrees) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+
+ double rad = Math.toRadians(degrees);
+ float sin = (float) Math.sin(rad);
+ float cos = (float) Math.cos(rad);
+
+ d.preTransform(getRotate(sin, cos));
}
-
- double rad = Math.toRadians(degrees);
- float sin = (float)Math.sin(rad);
- float cos = (float)Math.cos(rad);
-
- d.preTransform(getRotate(sin, cos));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preSkew(long native_object, float kx, float ky,
+ /*package*/ static void native_preSkew(long native_object, float kx, float ky,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getSkew(kx, ky, px, py));
}
-
- d.preTransform(getSkew(kx, ky, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preSkew(long native_object, float kx, float ky) {
+ /*package*/ static void native_preSkew(long native_object, float kx, float ky) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.preTransform(getSkew(kx, ky));
}
-
- d.preTransform(getSkew(kx, ky));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_preConcat(long native_object, long other_matrix) {
+ /*package*/ static void native_preConcat(long native_object, long other_matrix) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
Matrix_Delegate other = sManager.getDelegate(other_matrix);
- if (other == null) {
- return false;
+ if (d != null && other != null) {
+ d.preTransform(other.mValues);
}
-
- d.preTransform(other.mValues);
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postTranslate(long native_object, float dx, float dy) {
+ /*package*/ static void native_postTranslate(long native_object, float dx, float dy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getTranslate(dx, dy));
}
-
- d.postTransform(getTranslate(dx, dy));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postScale(long native_object, float sx, float sy,
+ /*package*/ static void native_postScale(long native_object, float sx, float sy,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getScale(sx, sy, px, py));
}
-
- d.postTransform(getScale(sx, sy, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postScale(long native_object, float sx, float sy) {
+ /*package*/ static void native_postScale(long native_object, float sx, float sy) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getScale(sx, sy));
}
-
- d.postTransform(getScale(sx, sy));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postRotate(long native_object, float degrees,
+ /*package*/ static void native_postRotate(long native_object, float degrees,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getRotate(degrees, px, py));
}
-
- d.postTransform(getRotate(degrees, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postRotate(long native_object, float degrees) {
+ /*package*/ static void native_postRotate(long native_object, float degrees) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getRotate(degrees));
}
-
- d.postTransform(getRotate(degrees));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postSkew(long native_object, float kx, float ky,
+ /*package*/ static void native_postSkew(long native_object, float kx, float ky,
float px, float py) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getSkew(kx, ky, px, py));
}
-
- d.postTransform(getSkew(kx, ky, px, py));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postSkew(long native_object, float kx, float ky) {
+ /*package*/ static void native_postSkew(long native_object, float kx, float ky) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
+ if (d != null) {
+ d.postTransform(getSkew(kx, ky));
}
-
- d.postTransform(getSkew(kx, ky));
- return true;
}
@LayoutlibDelegate
- /*package*/ static boolean native_postConcat(long native_object, long other_matrix) {
+ /*package*/ static void native_postConcat(long native_object, long other_matrix) {
Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
Matrix_Delegate other = sManager.getDelegate(other_matrix);
- if (other == null) {
- return false;
+ if (d != null && other != null) {
+ d.postTransform(other.mValues);
}
-
- d.postTransform(other.mValues);
- return true;
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index de2e592..25eaaf5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -428,6 +428,16 @@
}
@LayoutlibDelegate
+ /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
+ return false;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
+ // TODO
+ }
+
+ @LayoutlibDelegate
/*package*/ static float getTextSize(Paint thisPaint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index cdbe200..af22f44 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -32,10 +32,6 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.view.InflateException;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
import java.io.File;
@@ -155,6 +151,9 @@
@Override
public View inflate(int resource, ViewGroup root) {
Context context = getContext();
+ if (context instanceof ContextThemeWrapper) {
+ context = ((ContextThemeWrapper) context).getBaseContext();
+ }
if (context instanceof BridgeContext) {
BridgeContext bridgeContext = (BridgeContext)context;
@@ -217,43 +216,16 @@
}
private void setupViewInContext(View view, AttributeSet attrs) {
- if (getContext() instanceof BridgeContext) {
- BridgeContext bc = (BridgeContext) getContext();
- if (attrs instanceof BridgeXmlBlockParser) {
- BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs;
-
- // get the view key
- Object viewKey = parser.getViewCookie();
-
- if (viewKey == null) {
- int currentDepth = parser.getDepth();
-
- // test whether we are in an included file or in a adapter binding view.
- BridgeXmlBlockParser previousParser = bc.getPreviousParser();
- if (previousParser != null) {
- // looks like we inside an embedded layout.
- // only apply the cookie of the calling node (<include>) if we are at the
- // top level of the embedded layout. If there is a merge tag, then
- // skip it and look for the 2nd level
- int testDepth = mIsInMerge ? 2 : 1;
- if (currentDepth == testDepth) {
- viewKey = previousParser.getViewCookie();
- // if we are in a merge, wrap the cookie in a MergeCookie.
- if (viewKey != null && mIsInMerge) {
- viewKey = new MergeCookie(viewKey);
- }
- }
- } else if (mResourceReference != null && currentDepth == 1) {
- // else if there's a resource reference, this means we are in an adapter
- // binding case. Set the resource ref as the view cookie only for the top
- // level view.
- viewKey = mResourceReference;
- }
- }
-
- if (viewKey != null) {
- bc.addViewKey(view, viewKey);
- }
+ Context context = getContext();
+ if (context instanceof ContextThemeWrapper) {
+ context = ((ContextThemeWrapper) context).getBaseContext();
+ }
+ if (context instanceof BridgeContext) {
+ BridgeContext bc = (BridgeContext) context;
+ // get the view key
+ Object viewKey = getViewKeyFromParser(attrs, bc, mResourceReference, mIsInMerge);
+ if (viewKey != null) {
+ bc.addViewKey(view, viewKey);
}
}
}
@@ -270,4 +242,44 @@
public LayoutInflater cloneInContext(Context newContext) {
return new BridgeInflater(this, newContext);
}
+
+ /*package*/ static Object getViewKeyFromParser(AttributeSet attrs, BridgeContext bc,
+ ResourceReference resourceReference, boolean isInMerge) {
+
+ if (!(attrs instanceof BridgeXmlBlockParser)) {
+ return null;
+ }
+ BridgeXmlBlockParser parser = ((BridgeXmlBlockParser) attrs);
+
+ // get the view key
+ Object viewKey = parser.getViewCookie();
+
+ if (viewKey == null) {
+ int currentDepth = parser.getDepth();
+
+ // test whether we are in an included file or in a adapter binding view.
+ BridgeXmlBlockParser previousParser = bc.getPreviousParser();
+ if (previousParser != null) {
+ // looks like we are inside an embedded layout.
+ // only apply the cookie of the calling node (<include>) if we are at the
+ // top level of the embedded layout. If there is a merge tag, then
+ // skip it and look for the 2nd level
+ int testDepth = isInMerge ? 2 : 1;
+ if (currentDepth == testDepth) {
+ viewKey = previousParser.getViewCookie();
+ // if we are in a merge, wrap the cookie in a MergeCookie.
+ if (viewKey != null && isInMerge) {
+ viewKey = new MergeCookie(viewKey);
+ }
+ }
+ } else if (resourceReference != null && currentDepth == 1) {
+ // else if there's a resource reference, this means we are in an adapter
+ // binding case. Set the resource ref as the view cookie only for the top
+ // level view.
+ viewKey = resourceReference;
+ }
+ }
+
+ return viewKey;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
new file mode 100644
index 0000000..22232f3
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2014 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.view;
+
+import android.content.Context;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.internal.view.menu.BridgeMenuItemImpl;
+import com.android.internal.view.menu.MenuView;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.AttributeSet;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link MenuInflater}
+ * <p/>
+ * Through the layoutlib_create tool, the original methods of MenuInflater have been
+ * replaced by calls to methods of the same name in this delegate class.
+ * <p/>
+ * The main purpose of the class is to get the view key from the menu xml parser and add it to
+ * the menu item. The view key is used by the IDE to match the individual view elements to the
+ * corresponding xml tag in the menu/layout file.
+ * <p/>
+ * For Menus, the views may be reused and the {@link MenuItem} is a better object to hold the
+ * view key than the {@link MenuView.ItemView}. At the time of computation of the rest of {@link
+ * ViewInfo}, we check the corresponding view key in the menu item for the view and add it
+ */
+public class MenuInflater_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static void emptyMethod(MenuInflater thisInflater, MenuItem menuItem,
+ AttributeSet attrs) {
+ if (menuItem instanceof BridgeMenuItemImpl) {
+ Context context = thisInflater.getContext();
+ if (context instanceof ContextThemeWrapper) {
+ context = ((ContextThemeWrapper) context).getBaseContext();
+ }
+ if (context instanceof BridgeContext) {
+ Object viewKey = BridgeInflater.getViewKeyFromParser(
+ attrs, ((BridgeContext) context), null, false);
+ ((BridgeMenuItemImpl) menuItem).setViewCookie(viewKey);
+ return;
+ }
+ }
+ // This means that Bridge did not take over the instantiation of some object properly.
+ // This is most likely a bug in the LayoutLib code.
+ Bridge.getLog().warning(LayoutLog.TAG_BROKEN,
+ "Action Bar Menu rendering may be incorrect.", null);
+
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void emptyMethod(MenuInflater thisInflater, SubMenu subMenu,
+ AttributeSet parser) {
+ emptyMethod(thisInflater, subMenu.getItem(), parser);
+ }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
new file mode 100644
index 0000000..4bef424
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.internal.view.menu;
+
+/**
+ * An extension of the {@link MenuItemImpl} to store the view cookie also.
+ */
+public class BridgeMenuItemImpl extends MenuItemImpl {
+
+ /**
+ * An object returned by the IDE that helps mapping each View to the corresponding XML tag in
+ * the layout. For Menus, we store this cookie here and attach it to the corresponding view
+ * at the time of rendering.
+ */
+ private Object viewCookie;
+
+ /**
+ * Instantiates this menu item.
+ */
+ BridgeMenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
+ CharSequence title, int showAsAction) {
+ super(menu, group, id, categoryOrder, ordering, title, showAsAction);
+ }
+
+
+ public Object getViewCookie() {
+ return viewCookie;
+ }
+
+ public void setViewCookie(Object viewCookie) {
+ this.viewCookie = viewCookie;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java
new file mode 100644
index 0000000..505fb81
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 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.internal.view.menu;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link MenuBuilder}
+ * <p/>
+ * Through the layoutlib_create tool, the original methods of {@code MenuBuilder} have been
+ * replaced by calls to methods of the same name in this delegate class.
+ */
+public class MenuBuilder_Delegate {
+ /**
+ * The method overrides the instantiation of the {@link MenuItemImpl} with an instance of
+ * {@link BridgeMenuItemImpl} so that view cookies may be stored.
+ */
+ @LayoutlibDelegate
+ /*package*/ static MenuItemImpl createNewMenuItem(MenuBuilder thisMenu, int group, int id,
+ int categoryOrder, int ordering, CharSequence title, int defaultShowAsAction) {
+ return new BridgeMenuItemImpl(thisMenu, group, id, categoryOrder, ordering, title,
+ defaultShowAsAction);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 6595ce1..08e9d99 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -58,6 +58,7 @@
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -101,6 +102,7 @@
private final ApplicationInfo mApplicationInfo;
private final IProjectCallback mProjectCallback;
private final WindowManager mWindowManager;
+ private final DisplayManager mDisplayManager;
private Resources.Theme mTheme;
@@ -149,6 +151,7 @@
}
mWindowManager = new WindowManagerImpl(mMetrics);
+ mDisplayManager = new DisplayManager(this);
}
/**
@@ -455,6 +458,10 @@
return new PowerManager(this, new BridgePowerManager(), new Handler());
}
+ if (DISPLAY_SERVICE.equals(service)) {
+ return mDisplayManager;
+ }
+
throw new UnsupportedOperationException("Unsupported Service: " + service);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index afcadef..9787432 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -28,7 +28,6 @@
import com.android.ide.common.rendering.api.IAnimationListener;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.IProjectCallback;
-import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceReference;
@@ -39,6 +38,12 @@
import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.internal.util.XmlUtils;
+import com.android.internal.view.menu.ActionMenuItemView;
+import com.android.internal.view.menu.BridgeMenuItemImpl;
+import com.android.internal.view.menu.IconMenuItemView;
+import com.android.internal.view.menu.ListMenuItemView;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuView;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
@@ -101,11 +106,10 @@
/**
* Class implementing the render session.
- *
+ * <p/>
* A session is a stateful representation of a layout file. It is initialized with data coming
* through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
* be done on the layout.
- *
*/
public class RenderSessionImpl extends RenderAction<SessionParams> {
@@ -172,7 +176,7 @@
@Override
public Result init(long timeout) {
Result result = super.init(timeout);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
return result;
}
@@ -196,6 +200,7 @@
// FIXME: find those out, and possibly add them to the render params
boolean hasNavigationBar = true;
+ //noinspection ConstantConditions
IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
metrics, Surface.ROTATION_0,
hasNavigationBar);
@@ -229,10 +234,9 @@
BridgeContext context = getContext();
boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
- ActionBarLayout actionBar = null;
// the view group that receives the window background.
- ViewGroup backgroundView = null;
+ ViewGroup backgroundView;
if (mWindowIsFloating || params.isForceNoDecor()) {
backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
@@ -266,7 +270,7 @@
NavigationBar navigationBar = createNavigationBar(context,
hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
topLayout.addView(navigationBar);
- } catch (XmlPullParserException e) {
+ } catch (XmlPullParserException ignored) {
}
}
@@ -322,7 +326,7 @@
StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
layoutDirection, params.isRtlSupported());
topLayout.addView(statusBar);
- } catch (XmlPullParserException e) {
+ } catch (XmlPullParserException ignored) {
}
}
@@ -339,20 +343,16 @@
// if the theme says no title/action bar, then the size will be 0
if (mActionBarSize > 0) {
- try {
- actionBar = createActionBar(context, params);
- backgroundLayout.addView(actionBar);
- actionBar.createMenuPopup();
- mContentRoot = actionBar.getContentRoot();
- } catch (XmlPullParserException e) {
-
- }
+ ActionBarLayout actionBar = createActionBar(context, params);
+ backgroundLayout.addView(actionBar);
+ actionBar.createMenuPopup();
+ mContentRoot = actionBar.getContentRoot();
} else if (mTitleBarSize > 0) {
try {
TitleBar titleBar = createTitleBar(context,
hardwareConfig.getDensity(), params.getAppLabel());
backgroundLayout.addView(titleBar);
- } catch (XmlPullParserException e) {
+ } catch (XmlPullParserException ignored) {
}
}
@@ -374,7 +374,7 @@
NavigationBar navigationBar = createNavigationBar(context,
hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
topLayout.addView(navigationBar);
- } catch (XmlPullParserException e) {
+ } catch (XmlPullParserException ignored) {
}
}
@@ -399,7 +399,7 @@
postInflateProcess(view, params.getProjectCallback());
// get the background drawable
- if (mWindowBackground != null && backgroundView != null) {
+ if (mWindowBackground != null) {
Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
backgroundView.setBackground(d);
}
@@ -476,6 +476,7 @@
// first measure the full layout, with EXACTLY to get the size of the
// content as it is inside the decor/dialog
+ @SuppressWarnings("deprecation")
Pair<Integer, Integer> exactMeasure = measureView(
mViewRoot, mContentRoot.getChildAt(0),
mMeasuredScreenWidth, MeasureSpec.EXACTLY,
@@ -483,6 +484,7 @@
// now measure the content only using UNSPECIFIED (where applicable, based on
// the rendering mode). This will give us the size the content needs.
+ @SuppressWarnings("deprecation")
Pair<Integer, Integer> result = measureView(
mContentRoot, mContentRoot.getChildAt(0),
mMeasuredScreenWidth, widthMeasureSpecMode,
@@ -558,7 +560,7 @@
mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
}
- if (freshRender && newImage == false) {
+ if (freshRender && !newImage) {
Graphics2D gc = mImage.createGraphics();
gc.setComposite(AlphaComposite.Src);
@@ -573,7 +575,8 @@
mViewRoot.draw(mCanvas);
}
- mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), false);
+ mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
+ false);
// success!
return SUCCESS.createResult();
@@ -603,6 +606,7 @@
* @param heightMode the MeasureSpec mode to use for the height.
* @return the measured width/height if measuredView is non-null, null otherwise.
*/
+ @SuppressWarnings("deprecation") // For the use of Pair
private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
int width, int widthMode, int height, int heightMode) {
int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
@@ -633,7 +637,7 @@
BridgeContext context = getContext();
// find the animation file.
- ResourceValue animationResource = null;
+ ResourceValue animationResource;
int animationId = 0;
if (isFrameworkAnimation) {
animationResource = context.getRenderResources().getFrameworkResource(
@@ -723,7 +727,7 @@
// add it to the parentView in the correct location
Result result = addView(parentView, child, index);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
return result;
}
@@ -793,13 +797,13 @@
public void run() {
Result result = moveView(previousParent, newParentView, childView, index,
params);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
listener.done(result);
}
// ready to do the work, acquire the scene.
result = acquire(250);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
listener.done(result);
return;
}
@@ -857,7 +861,7 @@
}
Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
return result;
}
@@ -991,7 +995,7 @@
}
Result result = removeView(parent, childView);
- if (result.isSuccess() == false) {
+ if (!result.isSuccess()) {
return result;
}
@@ -1019,7 +1023,7 @@
private void findBackground(RenderResources resources) {
- if (getParams().isBgColorOverridden() == false) {
+ if (!getParams().isBgColorOverridden()) {
mWindowBackground = resources.findItemInTheme("windowBackground",
true /*isFrameworkAttr*/);
if (mWindowBackground != null) {
@@ -1036,7 +1040,7 @@
boolean windowFullscreen = getBooleanThemeValue(resources,
"windowFullscreen", false /*defaultValue*/);
- if (windowFullscreen == false && mWindowIsFloating == false) {
+ if (!windowFullscreen && !mWindowIsFloating) {
// default value
mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
@@ -1090,7 +1094,7 @@
boolean windowNoTitle = getBooleanThemeValue(resources,
"windowNoTitle", false /*defaultValue*/);
- if (windowNoTitle == false) {
+ if (!windowNoTitle) {
// default size of the window title bar
mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
@@ -1117,7 +1121,7 @@
}
private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
- if (hasSoftwareButtons() && mWindowIsFloating == false) {
+ if (hasSoftwareButtons() && !mWindowIsFloating) {
// default value
mNavigationBarSize = 48; // ??
@@ -1131,15 +1135,12 @@
int shortSize = hardwareConfig.getScreenHeight();
// compute in dp
- int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
+ int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
+ hardwareConfig.getDensity().getDpiValue();
- if (shortSizeDp < 600) {
- // 0-599dp: "phone" UI with bar on the side
- barOnBottom = false;
- } else {
- // 600+dp: "tablet" UI with bar on the bottom
- barOnBottom = true;
- }
+ // 0-599dp: "phone" UI with bar on the side
+ // 600+dp: "tablet" UI with bar on the bottom
+ barOnBottom = shortSizeDp >= 600;
}
if (barOnBottom) {
@@ -1190,13 +1191,15 @@
}
/**
- * Post process on a view hierachy that was just inflated.
- * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
+ * Post process on a view hierarchy that was just inflated.
+ * <p/>
+ * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
* {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
* based on the content of the {@link FrameLayout}.
* @param view the root view to process.
* @param projectCallback callback to the project.
*/
+ @SuppressWarnings("deprecation") // For the use of Pair
private void postInflateProcess(View view, IProjectCallback projectCallback)
throws PostInflateException {
if (view instanceof TabHost) {
@@ -1299,7 +1302,7 @@
"TabHost requires a TabWidget with id \"android:id/tabs\".\n");
}
- if ((v instanceof TabWidget) == false) {
+ if (!(v instanceof TabWidget)) {
throw new PostInflateException(String.format(
"TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
"View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
@@ -1308,12 +1311,14 @@
v = tabHost.findViewById(android.R.id.tabcontent);
if (v == null) {
- // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
+ // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
+ //noinspection SpellCheckingInspection
throw new PostInflateException(
"TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
}
- if ((v instanceof FrameLayout) == false) {
+ if (!(v instanceof FrameLayout)) {
+ //noinspection SpellCheckingInspection
throw new PostInflateException(String.format(
"TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
"View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
@@ -1321,7 +1326,7 @@
FrameLayout content = (FrameLayout)v;
- // now process the content of the framelayout and dynamically create tabs for it.
+ // now process the content of the frameLayout and dynamically create tabs for it.
final int count = content.getChildCount();
// this must be called before addTab() so that the TabHost searches its TabWidget
@@ -1339,13 +1344,13 @@
}
});
tabHost.addTab(spec);
- return;
} else {
- // for each child of the framelayout, add a new TabSpec
+ // for each child of the frameLayout, add a new TabSpec
for (int i = 0 ; i < count ; i++) {
View child = content.getChildAt(i);
String tabSpec = String.format("tab_spec%d", i+1);
int id = child.getId();
+ @SuppressWarnings("deprecation")
Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
String name;
if (resource != null) {
@@ -1468,13 +1473,13 @@
ViewInfo result;
if (isContentFrame) {
result = new ViewInfo(view.getClass().getName(),
- getContext().getViewKey(view),
+ getViewKey(view),
view.getLeft(), view.getTop() + offset, view.getRight(),
view.getBottom() + offset, view, view.getLayoutParams());
} else {
result = new SystemViewInfo(view.getClass().getName(),
- getContext().getViewKey(view),
+ getViewKey(view),
view.getLeft(), view.getTop(), view.getRight(),
view.getBottom(), view, view.getLayoutParams());
}
@@ -1495,6 +1500,32 @@
return result;
}
+ /**
+ * The cookie for menu items are stored in menu item and not in the map from View stored in
+ * BridgeContext.
+ */
+ private Object getViewKey(View view) {
+ BridgeContext context = getContext();
+ if (!(view instanceof MenuView.ItemView)) {
+ return context.getViewKey(view);
+ }
+ MenuItemImpl menuItem;
+ if (view instanceof ActionMenuItemView) {
+ menuItem = ((ActionMenuItemView) view).getItemData();
+ } else if (view instanceof ListMenuItemView) {
+ menuItem = ((ListMenuItemView) view).getItemData();
+ } else if (view instanceof IconMenuItemView) {
+ menuItem = ((IconMenuItemView) view).getItemData();
+ } else {
+ menuItem = null;
+ }
+ if (menuItem instanceof BridgeMenuItemImpl) {
+ return ((BridgeMenuItemImpl) menuItem).getViewCookie();
+ }
+
+ return null;
+ }
+
private void invalidateRenderingSize() {
mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
}
@@ -1545,8 +1576,7 @@
/**
* Creates the action bar. Also queries the project callback for missing information.
*/
- private ActionBarLayout createActionBar(BridgeContext context, SessionParams params)
- throws XmlPullParserException {
+ private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
ActionBarLayout actionBar = new ActionBarLayout(context, params);
actionBar.setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index b16b4aa..19d249b 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -253,4 +253,14 @@
return true;
}
+
+ @LayoutlibDelegate
+ /*package*/ static void setDefaultLocale(String locale) {
+ ICU.setDefaultLocale(locale);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static String getDefaultLocale() {
+ return ICU.getDefaultLocale();
+ }
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index e0c05de..986b911 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -143,6 +143,8 @@
"android.view.ViewRootImpl#isInTouchMode",
"android.view.WindowManagerGlobal#getWindowManagerService",
"android.view.inputmethod.InputMethodManager#getInstance",
+ "android.view.MenuInflater#emptyMethod",
+ "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
"com.android.internal.util.XmlUtils#convertValueToInt",
"com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
};